angular infinite digest loop from ng-model using g

2019-07-17 06:01发布

Here is the html:

<select style="width: 100%;" ng-model="vm.orgType" ng-model-options="{getterSetter: true}" ng-options="orgType as orgType.ORGANIZATION_TYPE for orgType in vm.orgTypes">
                                </select>

and here is the getter/setter function:

function orgType(selectedType) {
            if (arguments.length == 0)
                return orgType.selectedOrgType || { ORGANIZATION_TYPE: 'Organization Type', ORGANIZATION_TYPE_ID: null };

            orgType.selectedOrgType = selectedType;
            if (selectedType.ORGANIZATION_TYPE_ID) {
                if (vm.registrant.StakeholderOrgs[0])
                    vm.registrant.StakeholderOrgs[0] = selectedType.ORGANIZATION_TYPE_ID;
                else
                    vm.registrant.StakeholderOrgs.push(selectedType.ORGANIZATION_TYPE_ID);
            }
            else
                vm.registrant.StakeholderOrgs.splice(0);
        }

the following line:

return orgType.selectedOrgType || { ORGANIZATION_TYPE: 'Organization Type', ORGANIZATION_TYPE_ID: null };

throws the infinite digest loop error.

Let me explain what I am trying to do here. I need to push the id onto a list if there is a selection made. I realize that I could just do an ng-model on some variable selectedOrgType and then just put my logic in an ng-change. However, I am trying to make a dropdown that does not create any unnecessary model variables. Instead, I was hoping to just put the logic in a getter/setter, that seems more appropriate to me. One of vm.orgTypes is { ORGANIZATION_TYPE: 'Organization Type', ORGANIZATION_TYPE_ID: null }, I was hoping that would be my default value instead I get this digest error, don't understand where it is coming from.

1条回答
我只想做你的唯一
2楼-- · 2019-07-17 06:13

When you add ng-model attribute, angular add internal watch, that check value on every digest loop, and if value changed - run digest again.

In you case you return object literal. In javascript when you compare two literals, even with same structure - you get false

({a:1} == {a:1}) // false

because this really two different object.

So, when you return object literal in your getter, watch check it with previous value, and, as i say above, if you return literal - get false

So you get your error with infinite digest.

For solving you just need return same object.

If you have this object inside array, like

vm.orgTypes=[
    { ORGANIZATION_TYPE: 'Organization Type', ORGANIZATION_TYPE_ID: null }
];

So you just need use it directly:

 return orgType.selectedOrgType || orgTypes[0];

Yer another way: just save default falue to varible and use it

var defaultSelect = { ORGANIZATION_TYPE: 'Organization Type', ORGANIZATION_TYPE_ID: null };

....

function orgType(selectedType) {
    if (arguments.length == 0)
        return orgType.selectedOrgType || defaultSelect;

In this case you would return same element in default case, so avoid infinite digest loot.

查看更多
登录 后发表回答