Soltani Neji Soltani Neji - 1 month ago 12
AngularJS Question

AngularJS won't set scope variable with ng-click

All I want is to set a scope

change
before opening the modal
so I put
ng-click="change = false;mode = 'edit';"
in the edit button

The wrong scenario is when I click on edit the scope should be
false

but if I change it to
true
by pressing the change button and then I close the modal and I click again on edit to open the modal again you can see that the scope is still true while it should be reset back to false

Any explanations ?

I made this exemple in Plunker ,

Here's the code:



<!DOCTYPE html>
<html ng-app="app">

<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<script>
var app = angular.module('app', []);
app.controller('MainCtrl', function($scope) {
});
</script>
</head>

<body ng-controller="MainCtrl">
<button type="button" class="btn btn-info btn-lg" data-toggle="modal" data-target="#myModal" ng-click="mode = 'add'">Add</button>
<button type="button" class="btn btn-info btn-lg" data-toggle="modal" data-target="#myModal" ng-click="change = false;mode = 'edit';">Edit</button>
<!-- Modal -->
<div class="modal fade" id="myModal" role="dialog" ng-switch on="mode">
<div class="modal-dialog">

<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">&times;</button>
<h4 class="modal-title" ng-switch-when="add">Add</h4>
<h4 class="modal-title" ng-switch-when="edit">Edit</h4>
</div>
<div class="modal-body">
<p>{{mode}} </p>
<button type="button" class="btn btn-default" ng-click="change = false" ng-show="change">Change</button>
<button type="button" class="btn btn-default" ng-click="change = true" ng-show="!change">Revert</button>
<p>{{change}} </p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>

</div>
</div>
</body>

</html>




Answer Source

This is because angular uses prototypal inheritance while creating non-isolated scope. Since ng-repeat/ng-if/ng-if these template directives creates prototypically inherited child scope while rendering transcluded DOM in it. Worth reading What are the nuances of scope prototypal / prototypical inheritance in AngularJS?. This kind of issue generally happens with primitive data types like string, bool, number, etc. General practice to solve this issue would be using object(reference type). Using reference type while defining models on angular scope called as Dot Rule.

In your scenario you could consider creating $scope.model = {} object which will eventually hold your all properties related to that entity. While using them on HTML use model.change & model.edit.

You could even use controllerAs syntax while defining your controller, it bound all the binding variables to this(context) instead of $scope.

Demo Plunker