dabadaba dabadaba - 3 months ago 24
AngularJS Question

ng-model not being updated outside of the scope

I am binding an

to an input, but the value of the variable it's bound to is not being updated outside of the
where that directive is declared:

<div input-field
ng-if="startTypes.selected.value == 'LocalDate' || startTypes.selected.value == 'LocalDateTime'">
<input id="date" type="text" ng-model="date" input-date>
<label for="date">Date</label>
Date inner scope: {{date}}
Date outer scope: {{date}}

When selecting a new date, ony the inner
is updated. The outer one remains with the old value (which might be either
or not depending if I declared it in the controller, it doesn't matter).

I am using angular-materialize, I am not sure if this is the source of the issue but it doesn't make sense because it is a specific framework for angular to work with the CSS framework materializecss.

This is the component I am using.


I have tried declaring
in the controller as
$scope.date = new Date()
and indeed the current date is loaded in the date picker. However when a date is selected and the model changes, it's only updated locally (inner scope), while in the outer scope the old value remains.


As ng-if creates a child scope which is Prototypically inherited from its current scope while inserting inner template to DOM, hence in this case ng-model getting created inside ng-if's child scope. So what happening is while creating a child scope it carries the primitive datatype values & reference(object) datatypes values to child scope, thats why you can see the outer scope date is getting value inside ng-if date field(only first time). But when you update the value in date you will not see the value gets updated to outer scope. Because the way child scope has create primitive type value not carry their references, where as objects are carried with their references. So you can create a object like $scope.model = {} & then define a property into it, that will work. Because object are carried with their references to child scope, updating inner object would sync the outer object as well(they both are same). This rule is called as Dot Rule by which you can fix your issue.

$scope.model = {};
$scope.model.date = new Date();

More convenient way to avoid such kind of scope hierarchy is using controllerAs pattern while using controller on HTML. In this case you shouldn't be using $scope instead you will bind all the properties to controller function context (this). Thereafter when using controller you can use alias of controller to get the values of controller like ng-controller="myCtrl as vm"(here vm is alias of controller which has all information binding to this)


<div input-field
     ng-if="vm.startTypes.selected.value == 'LocalDate' || vm.startTypes.selected.value == 'LocalDateTime'">
  <input id="date" type="text" ng-model="vm.date" input-date>
  <label for="date">Date</label>
  Date inner scope: {{vm.date}}
Date outer scope: {{vm.date}}