0

I'm going nuts!

Is it possible to create a directive that renders different times (00:15,00:30,00:45) etc into a select box where my ngModel uses objects for hours and minutes like below?

{
   "h" : 1,
   "m" : 30
}

My idea is to use ngModel.$formatters, ngModel.$parsers and ngModel.$render to make it possible have bi-directional bindings between the textual representation of the select box and the ngModel.

See JSFiddle http://jsfiddle.net/52kUy/23/

I have been playing with a solution to attach an ng-change to the selectbox but I also need the ng-change to be available in the application to react to time changes.

Note: To simplify the code I have removed padding of the strings (00:15 => 0:15 etc).

Super thankful for any directions.

2 Answers 2

1

Is this what you meant?

HTML:

<div ng-app="HelloApp" ng-controller="HelloController">
    <select ng-model="blah" ng-options="value as value | myfilter for value in values"></select>
    {{blah}}
</div>

JS:

app.filter('myfilter', function() { 
    return function(obj) {
        return obj.h + ':' + obj.m;
    }
});
app.controller('HelloController', function($scope) {
    $scope.values = [{
       "h" : 1,
       "m" : 30
    }, {
       "h" : 1,
       "m" : 25
    }];

jsfiddle

EDIT:

Answering your question, if you want to initialize a the select model and your model is an object the comparison will be done by reference; have a look at this: angular docs, specially this line: "Note: ngModel compares by reference, not value. This is important when binding to an array of objects. See an example in this jsfiddle." Unless you define a track by expression, in your case we could do something like this:

HTML:

<div ng-app="HelloApp" ng-controller="HelloController">
    <select ng-model="blah" ng-options="value as value | myfilter for value in values track by value.h + ":" + value.m"></select>
    {{blah}}
</div>

JS:

app.filter('myfilter', function() { 
    return function(obj) {
        return obj.h + ':' + obj.m;
    }
});
app.controller('HelloController', function($scope) {
    $scope.values = [{
       "h" : 1,
       "m" : 30
    }, {
       "h" : 1,
       "m" : 25
    }];


   $scope.blah = {h: 1, m: 25};
});

plunker

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

2 Comments

Thank for the tip of using filter! Updated the fiddle jsfiddle.net/niclas_lindberg/37dqrb08/2 to try it. But the select doesn't initialize with the correct value when I define $scope.blah with an object with a time that exists in the array. If I create a value object referred to by the array and set in $scope.blah it works. (By reference). Any ideas?
Correct. I made the same discovery. Example below. Accepted answer. :)
0

Ng-options work by reference so by ffurther extending Wawy's solution with track by in ng-options it works by value.

HTML:

<div ng-app="TestApp" ng-controller="HelloController">
    <select ng-model="blah" ng-options="value as value | myfilter for value in values track by id(value)">    </select>
    {{blah}}
</div>

JS:

var app = angular.module('TestApp',[]);

app.filter('myfilter', function() { 
    return function(obj) {
        return obj.h + ':' + obj.m;
    }
});

app.controller('TestController', function($scope) {

    $scope.id = function(obj) {
        return obj.h + ":" + obj.m;  
    };

    $scope.values = [{
       "h" : 1,
       "m" : 30
    },
    {
       "h" : 1,
       "m" : 25
    }];

    $scope.blah = {"h":1,"m":25}; 

});

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.