antacerod
antacerod

Reputation: 1420

Conditional ng-model binding in angularjs

I have a model which is an array that needs to handle complex and simple elements :

{
    "object" :[
               "element1.html",
               "element2.html",
               {
                   "url:"element3.html",
                   "title" : "Title 3"
               },
               "element4.html",
               "element5.html"
            ]
}

Is there some way to make a select which can handle both simple and complex elements in angularjs (showing url from the complexs)?

Approach 1

I mean some like that:

ng-model="(object[$index].url ? object[$index].url : object[$index])"

Approach 2

Make a normalized object that will have the complex structure for each object with empty arrays and a file type indicating whether is simple or complex.

Could I make some magic with angular to avoid the second approach?

Thanks!

Upvotes: 26

Views: 39677

Answers (2)

Konstantin Krass
Konstantin Krass

Reputation: 8646

You could use ngSwitch or ngIf and place the correct element then.

With ngIf for example:

<input ngIf="object[$index].url" ngModel="object[$index].url">
<input ngIf="!object[$index].url" ngModel="object[$index]">

If the condition is not met, angular will completely remove the dom element, till the condition will meet.

Upvotes: 22

laggingreflex
laggingreflex

Reputation: 34667

Using getters and setters

You can define getters and setters on an object and put logic in it to retrieve/set whatever other object you wanted to get/modify conditionally.

Angular has a ng-model-options="{getterSetter:true}" which you can use as follows:

input(ng-model="data" ng-model-options="{getterSetter:true}")

var data1 = "data 1";
var data2 = "data 2";
$scope.data = function(newVal) {
    if (condition) {
        if (angular.isDefined(newVal))
            data1 = newVal;
        return data1;
    } else {
        if (angular.isDefined(newVal))
            data2 = newVal;
        return data2;
    }
};

However, and this might be just in my case, it alone didn't work or not as expected.

There's also the JavaScript's default way to do the same using Object.defineProperty

var data1 = "data 1";
var data2 = "data 2";
Object.defineProperty($scope, 'data', {
    get: function() {
        if(condition)
            return data1;
        else
            return data2;
    },
    set: function(newVal) {
        if(condition)
            data1 = newVal;
        else
            data2 = newVal;
    }
});

Again, this might be just in my case, but using only either of them alone didn't work or didn't work as expected. So I used them both together and it works perfectly.

Upvotes: 15

Related Questions