4

When I get a model from the server it looks like this:

$scope.m = 
{
   name: "John",
   Dt:   "2013-10-03T18:47:33.5049087-07:00"
};

The view looks like:

<input title="Date" ui-date ng-model="m.Dt" />

I set the default date format on the jQuery datepicker to:

$.datepicker.setDefaults({dateFormat: 'mm-dd-yy'});

The initial value of the input stays "2013-10-03T18:47:33.5049087-07:00" though. It only formats as mm-dd-yy if I use the datepicker to change the date.

How can I get the initial value to also be in mm-dd-yy format?

3 Answers 3

1

Your $scope.m.Dt property should be of date type, not string.

$scope.m = 
{
   name: "John",
   Dt:   new Date()
};

To set date format use ui-date-format directive, like:

<input title="Date" ui-date ui-date-format="mm-dd-yy" ng-model="m.Dt" />

See example in readme: https://github.com/angular-ui/ui-date#ui-date-format-directive

Sign up to request clarification or add additional context in comments.

2 Comments

Yes, I'm aware it works with Date objects, but in a real world example your data comes from the server likely via JSON and your dates will not be objects, but strings. I can write a method to recurse thru the model and convert date strings to objects, but I was thinking for such a common scenario it would already be handled.
It's not handled in angular, but you can create http interceptor with recursive method to convert date strings to objects as you mentioned. See this post for example: aboutcode.net/2013/07/27/json-date-parsing-angularjs.html
0

The problem is that the "date" is just a string, Angular wants a native Date object (or a timestamp).

I've found two ways of dealing with this: Scrub the data right away or watch the variable and reassign its type.

My preferred solution is to munge the data when it's brought in. Since I know the object has a date, I just scrub the JSON data from the $http success promise like this:

$http.get('data.json').success(function(data) {
    data.date = Date.parse(data.date);
    $scope.model = data;
}

That converts the data before it's assigned to $scope, so Angular will see $scope.model.date as a native JS Date object format it correctly.

The other solution is to specifically $watch the variable's type. Somewhere in the controller, add this:

$scope.$watch('model.date', function() {
    if (typeof $scope.model.date === 'string') {
        $scope.model.date = Date.parse($scope.model.date);
    }
});

That checks the type everytime $scope.model.date is modified. Obviously, that's more overhead, but might be useful in some cases.

Comments

0

I had the same issue. Here is what I did using Jquery-UI calendar with Angularjs

date format was "2015-03-24T04:00:00"

First trim the date string to get only year, month, and date.

var date = "2015-03-24T04:00:00"
var formattedDate = date.match(/[\d-]+/).pop();
// formattedDate is now "2015-03-24" which is passed into
// the directive below as the input.$modelValue.

Now, inside your directive or controller do the following...

// Here is directive example.
link: function( scope, element, attrs, input ){

  element.datepicker( optionsObjectHere );
  setInitialDateFormatOnInput();

  function setInitialDateFormatOnInput(){
    setTimeout(function(){ // This timeout is required to delay the directive for the input.modelValue to resolve, however, no actual delay occurs!
      element.datepicker( "setDate", formatToJqueryUIDateFormat());
    });
  }

  function formatToJqueryUIDateFormat(){
    return $.datepicker.parseDate( 'yy-mm-dd', input.$modelValue );
    // 'yy-mm-dd' needs to match the input.$modelValue format from above. 
  }
} // link

This is how I use the entire jquery UI on my inputs.

HTML

<input type="text" class="inline" ng-model="inputValue" my-calendar-popup="calendarOptions" />

Where calendarOptions is the following object

  var calendarOptions = { minDate: 0, buttonImage: "calendar-icon.png", buttonImageOnly: 'true', showOn: "both", dateFormat: "MM d, yy" };

DIRECTIVE

app.directive('myCalendarPopup', function(){

  var defaultOptions = { minDate: 0, buttonImage: "calendar-icon.png",   buttonImageOnly: 'true', showOn: "both", dateFormat: "MM d, yy" };
  // defaultOptions just in case someone doesn't pass in options.

  return {
    require:'?ngModel',
    restrict: 'A',

    link: function( scope, element, attrs, input ){
      if ( !input ){ return; } // If no ngModel then return;

      element.datepicker( createCalendarOptions());
      setInitialDateFormatOnInput();

      function createCalendarOptions(){
        if( !attrs.rsCalendarPopup ){ return addRequiredJqueryFunction( defaultOptions );}
        return formatOptions();
      }

      function formatOptions() {
        var options = scope.$eval( attrs.rsCalendarPopup );
        // Turn string into object above.
        return addRequiredJqueryFunction( options );
      }

      function addRequiredJqueryFunction( options ){
        options.onSelect = changeDate;
        // add onSelect to passed in object and reference local changeDate function, which will update changes to input.$modelValue.
        return options;
      }

      function changeDate( date ){
        input.$setViewValue( date );
      }

      function setInitialDateFormatOnInput(){
        setTimeout(function(){
        // This timeout is required to delay the directive for the input.modelValue to resolve.
        // However, there is no actual timeout time. This is a must to get
        // Angular to behave.
          element.datepicker( "setDate", formatToJqueryUIDateFormat());
        });
      }

      function formatToJqueryUIDateFormat(){
        return $.datepicker.parseDate( 'yy-mm-dd', input.$modelValue );
        // 'yy-mm-dd' is not the format you want the calendar to be
        // it is the format the original date shows up as.
        // you set your actual formatting using the calendar options at
        // the top of this directive or inside the passed in options.
        // The key is called dateFormat, in this case it's set as
        // dateFormat: "MM d, yy" which makes June 30, 2015.
      }
    } // link
  } // return
});

Note: I can only get this to work in it's displayed configuration. I have added it to a controller, and even a directive controller and could not recreate the initial date condition. I have not found out why this is yet. Perhaps this solution works only within a link function that is embedded in another isolated scope directive and works due to specific timing.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.