10

I'm trying to make the materialize date picker editable. Here is the goal, the user can directly write the date in the input field or use the widget to pick a date.

I did something that is about to work on this jsfiddle. But there is a bug I'm trying to solve. When the user directly writes the date in the input, the picker needs to get the new value also (because I use a different format to submit the date and there is a an hidden input field to update). To accomplish that I tried to do

picker.set('select', $(this.val());

But it creates an infinite loop because the method set in materialize also triggers the event change on the input.

EDIT: oh i just found there is an issue open about that on github. Do you have any idea for a workaround?

Clemzd
  • 895
  • 2
  • 15
  • 35

1 Answers1

7

Any specific reason you want to do it in the change method?
Why not something like this?

this.change(function(event) {

});

this.bind('blur keypress',function(e){
  if (moment($(this).val(), "DD/MM/YYYY", true).isValid()) {
      var inputFieldDate=getFmtDate($(this).val());
      picker.set('select',inputFieldDate);
  }

});

This is a utility function to parse the date in DD/MM/YYY format and get a javascript Date object

function getFmtDate(s){
  var valx=new Array();
  if(s!=null && s.length>0){
      valx = s.split('/');
  }
  var d = new Date(valx[2],valx[1]-1,valx[0]);
  return d;
}

This works for me.

Update:

Once you attach a widget to an html element, the usual event callback functions do not work the way you expect them to. Their functionality is overridden by the widget. You cannot use the functions the same way you are used to and have to find a workaround. In short you cannot use the change function to set or unset the date because set triggrers a change event.

In your case you want to address multiple issues which are very common problems. You should be able to get a lot of examples online to achieve each one of those. What I've done is just one way of doing it.

  1. Populate the form in a non traditional way when the page loads.
  2. Initialize various plugins with values from the form when the page loads
  3. Initialize content from hidden fields when the form loads and update the hidden fields when submitting the form.
  4. Fetch the values by name (of the hidden fields) and use them to initialize the widgets.


I've used blur keypress just to give you an idea that all your requirements can be handled without using change. You use the events that work for you. You can set the date by binding picker to calendar object with this keyword and access it from its instance as shown below.

    (function($) {

      $.fn.calendar = function(options) {

    // Options du datepicker
        var settings = $.extend({
            editable: true,
            format: 'dd/mm/yyyy',
            formatSubmit: 'ddmmyyyy'
        },
        options
      );

    this.pickadate(settings);
    //var picker = this.pickadate(''); will not work
    this.picker = this.pickadate('picker');

    this.change(function(event) {

    });
    this.bind('blur keypress',function(e){
      if (moment($(this).val(), "DD/MM/YYYY", true).isValid()) {
            var inputFieldDate=getFmtDate($(this).val());
          picker.set('select',inputFieldDate);
      }
    
    });

    var $triggerIcon = $('<div class="col s2 center-align"><a class="btn-floating btn-large waves-effect waves-light trigger-datepicker">Date</a></div>');
    $triggerIcon.click(function(event) {
      event.stopPropagation();
      event.preventDefault();
      picker.open();
    });
    this.parent().after($triggerIcon);
    // Resolves picker opening for thing
    this.next().unbind("focus.toOpen");
    return this;
      };
    }(jQuery));

To set a date:

//This is how you set a date
var cal = $('.datepicker').calendar();
//You can access picker because we changed
//var picker to
//this.picker above in fn.calendar
cal.picker.set('select', getFmtDate($("[name=hiddenDate]").val()));
// The syntax is 
//cal.picker.set('select', new Date());

$('#formulaireDate').validate();

You have to convert your date to Date(). The below function should give you an idea. You can also use plugins like jquery dateFormat plugin.

function getFmtDate(s){
    var valx=new Array();
      if(s!=null && s.length>0){
                        valx = s.split('/');
              }
  var d = new Date(valx[2],valx[1]-1,valx[0]);
  return d;
}

This is your html.

<div class="row">
<div class="col s4">
  <input type="text" class="datepicker" />
  <input name="hiddenDate" type="hidden" value="12/12/2016">
</div>
</div>
Community
  • 1
  • 1
Shakeel
  • 184
  • 4
  • Ok, your solution works. But I'm sorry to say that but it's a workaround. Binding an other event to not trigger the 'change' event does not seems to be the correct way to do it. I can't accept that despistes I've used it and I can say it works. – Clemzd Mar 14 '16 at 18:35