As you used @ here, where the value from the attribute with the {{}} interpolation directive is required. And it looks like the directive is loaded first, and then the vm.index value is vm.index . Thus, changes do not occur in the current digest cycle. If you want them to be reflected, you need to start the digest cycle in a more secure way using $ timeout.
$timeout(function(){ vm.index = parseInt(vm.index, 10) })
First of all, this means that the value is converted to a decimal value. Adding will be performed in the html directive <h2>Item {{ vm.index + 1 }}</h2>
Working demo
Possible reason for this
According to @dsfq and my discussion, we went through the angular $compile API and found that their one method calls initializeDirectiveBindings , which only gets called when we use controllerAs in an isolated volume directive. In this function, there are switching cases for various @ , = and & bindings, since you use @ , which means that a one-way binding is called after the switch code code.
the code
case '@': if (!optional && !hasOwnProperty.call(attrs, attrName)) { destination[scopeName] = attrs[attrName] = void 0; } attrs.$observe(attrName, function(value) { if (isString(value)) { destination[scopeName] = value; } }); attrs.$$observers[attrName].$$scope = scope; if (isString(attrs[attrName])) {
In the above code, you can see that they put attrs.$observe , which is one type of observer that is usually used when the value has interpolation, for example, in our case itβs the same {{index}} , it means that this $observe gets evaluated when the digest cycle starts, so you need to put $timeout when creating the index value as decimal .
The reason for @dsfq's answer works because it uses = , provides a two-way binding, the code of which does not put the observer directly from the value of the selected area, here is the code . Thus, without a loop, the digest whose value is updated.