ngModel Changing to Child Scope - angularjs

When I edit a value through an input field that is bound (perhaps bound isn't the right term) to a parent controller's scope, it seems to re-bind to the child controller's scope. This eliminates my ability to affect the value with functions built into the parent scope (clicking the button in the example) which works BEFORE I edit the input field manually.
E.g:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Example - example-example85-production</title>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.0-beta.1/angular.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.0-beta.1/angular-animate.js"></script>
<script type="text/javascript">
angular.element(document.getElementsByTagName('head')).append(angular.element('<base href="' + window.location.pathname + '" />'));
</script>
</head>
<body ng-app="inputExample">
<script>
angular.module('inputExample', [])
.controller('ExampleController', ['$scope', function($scope) {
$scope.val = '1';
$scope.$watch('val',function(){
alert($scope.val);
});
$scope.set_val = function(){
$scope.val = 2;
}
}])
.controller('childController',['$scope', function($scope){}]);
</script>
<form name="testForm" ng-controller="ExampleController">
<div ng-controller="childController">
<input ng-model="val" />
<input type="button" ng-click="set_val()" value="change value"/>
</div>
</form>
</body>
</html>
http://plnkr.co/edit/cMz9dIMgnyImxQ0va7Wn?p=preview

childController creates a new scope that prototypically inherits from the ExampleController scope. Angular's use of prototypical inheritance and scope can be confusing, especially if you assume that prototypical inheritance behaves as inheritance does in other languages (C#, Java, etc).
If ExampleController.scope.val = 2, then the input will be initialized with the value 2, however, when the input modifies the value, it does so by setting
childController.val = 2.
Now both ExampleController.scope and childController.scope have a property val with a value of 2, but they are completely separate and not bound together.
This is why angular recommends using "dot notation" for models.
However, your childController looks to be unnecessary in your example and removing it will fix your problem. If you can't remove it (because your actual implementation is doing something with it, then change your models to "dot" notation.
<body ng-app="inputExample">
<script>
angular.module('inputExample', [])
.controller('ExampleController', ['$scope', function($scope) {
$scope.data = {};
$scope.data.val = '1';
$scope.$watch('data.val',function(){
alert($scope.data.val);
});
$scope.set_val = function(){
$scope.data.val = 2;
}
}])
.controller('childController',['$scope', function($scope){}]);
</script>
<form name="testForm" ng-controller="ExampleController">
<div ng-controller="childController">
<input ng-model="data.val" />
<input type="button" ng-click="set_val()" value="change value"/>
</div>
</form>
</body>
</html>
Here is the working Plunk.

Related

How to save the state of check box to local storage using AngularJS?

I want to save the current state of check box and reload it when open the page next time.
AngularJS:
var app = angular.module('MyApp', []);
app.controller('MyController', function ($scope, $window) {
var init = function () {
$scope.check = $window.localStorage.getItem("app3");
};
init();
$scope.Save = function () {
$window.localStorage.setItem("app3", $scope.check);
}
});
HTML:
<html ng-app="MyApp" xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<script src="angular-1.4.9.min.js"></script>
<script src="app.js"></script>
</head>
<body>
<div ng-controller="MyController">
<input id="check1" type="checkbox" ng-model="check" />
<input type="button" value="Save" ng-click="Save()" />
</div>
</body>
</html>
Dont use jquery with angular.
Attach a ng-model to your input box like so : and you can access the value of the input in your controller using $scope.check
your local storage setting will be like so :
$window.localStorage.setItem('app3',$scope.check);
Thats it! Kindly go through angular tutorials or their documentation to understand how angular works.

Angular expression not updated upon button press

I can successfully update an Angular expression immediately but it fails upon a button press. I need a little help here.
Here's the code.
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.5/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
</head>
<body>
<div ng-app="MyApp">
<div ng-controller="MyController">
<button id="myButton">Press</button>
{{myMessage}}
<script>
function setMessage(msg) {
angular.module('MyApp', [])
.controller('MyController', function($scope) {
$scope.myMessage = msg;
});
}
setMessage("first");
$(document).ready(function() {
$('#myButton').on('click', function( event ){
setMessage("second");
});
});
</script>
</div>
</div>
</body>
</html>
The first call which happens right away correctly updates the expression to "first". However the second call when the button is pressed fails to upate the expression to "second". What am I doing wrong?
First of all, good advice: remove jQuery from the project until you understand well why you should not use jQuery-style development with Angular app. Shortly, Angular has a specific event/parsing/compiling lifecycle that is not the same as just the flow we are used in jQuery projects. Take a look at this thread.
Then what you need to do is to use ngClick directive:
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular.min.js"></script>
<div ng-app="MyApp">
<div ng-controller="MyController">
<button ng-click="setMessage('second')">Press</button>
{{myMessage}}
</div>
</div>
<script>
angular.module('MyApp', [])
.controller('MyController', function($scope) {
$scope.myMessage = 'first';
$scope.setMessage = function(msg) {
$scope.myMessage = msg;
};
});
</script>
Remove the function around your angular module and you should use angular's ng-click directive to update your html on click:
<div ng-app="MyApp">
<div ng-controller="MyController">
<button id="myButton" ng-click="update('second')">Press</button>
{{myMessage}}
<script>
angular.module('MyApp', [])
.controller('MyController', function($scope) {
$scope.myMessage = "first";
$scope.update = function(msg){
$scope.myMessage = msg;
}
});
</script>
</div>
</div>
The documentation for ng-click: https://docs.angularjs.org/api/ng/directive/ngClick
Don't mix jQuery with angularjs, unless is totally needed. See this answer about it
you should use all the events, functions and directives providad by angularjs.
So your coude would look to something like this
<div ng-app="MyApp">
<div ng-controller="MyController">
<button ng-click="setMessage()">Press</button>
{{myMessage}}
<script>
function setMessage(msg) {
angular.module('MyApp', [])
.controller('MyController', function($scope) {
// set the original value for myMessage
$scope.myMessage = "first";
// update with second value
$scope.setMessage = function(){
$scope.myMessage = "second";
}
});
}
</script>
</div>
</div>
Of course you should organize this better, but this is the first approach
The main difference is that if you use the angular events (like ng-click in this case) it will let Angular knows what something has changed and that it has to update/refresh the view.
If you change something with jQuery, unless you force angular to know it (using $scope.$apply()) there is no way that angular knows by itself that the model has changed.

Binding controller properties in isolate scope

I am trying to get up to AngularJS directives and scope bindings. I will rather give my code and then ask question :
Here is my directive definition :
'use strict';
(function(){
var app = angular.module('gemStore', []);
var gem = {name:"Pearl",price:22.5 };
app.controller("StoreController",function(){
var self = this;
self.product = gem;
self.validateOnSubmit="myForm";
});
app.directive("requireOnSubmit",function(){
var directiveDefinitionObject = {
restrict:'A',
scope : {
validationFlag : '='
},
link : function(scope,ele,attr){
console.log(scope.validationFlag);
},
controller : "StoreController",
controllerAs : "store",
bindToController : true
};
return directiveDefinitionObject;
});}());
And Here is my html :
<!DOCTYPE html>
<html ng-app="gemStore">
<head>
<meta charset="utf-8">
<title></title>
</head>
<body ng-controller="StoreController as store">
<div>
<h3>{{store.product.name}} </h3> <h3>{{store.product.price}} </h3>
</div>
<form name="myForm">
<input type="text" name="test" require-on-submit />
</form>
</body>
<script type="text/javascript" src="resources/js/angular.min.js"></script>
<script type="text/javascript" src="app.js"></script>
Now I want to bind validationOnSubmit property on controller with validationFlag and it should be two-way binding.
I have tried adding
<input type="text" name="test" require-on-submit validationFlag="validationOnSubmit"/>
and in directive :
scope : {
validationFlag : '=validationFlag'
}
But doesn't work. How to achieve this?
I'm not sure if 2 way binding works with controller properies but the correct syntax would be
validationFlag="store.validationOnSubmit"
The StoreController will be initialized twice. Once on the body element and once with the directive. To avoid confusion you should remove the controller from the directive and if you need access to the controller use the require propery.

How to save input text to variable while typing in angularjs

Can anyone tell me how can I do that please?
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script>document.write('<base href="' + document.location + '" />');</script>
<link rel="stylesheet" href="style.css" />
<script data-require="angular.js#1.4.x" src="https://code.angularjs.org/1.4.0-rc.2/angular.js" data-semver="1.4.0-rc.2"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
<form name="form.one" ng-submit="submitForm()">
<input ng-model="name">
<input type="submit">
</form>
<p>Hello {{name}}!</p>
</body>
And my app.js is
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.name = "Name";
var data = {};
$scope.submitForm = function() {
var data = form.one.name;
};
});
How can I save input to the data variable? Is it possible to save on keypress?
To use your form with Angular, there's a few modifications you need to make for this code to work: first, you need to add the novalidate attribute to your form; it is used to disable the browser's native form validation. Angular will use it's own validation. Here's a few other modifications (they're explained in detail here):
<body ng-controller="MainCtrl">
<form novalidate>
<input ng-model="name">
<!-- The method for submitting the data goes on the button. -->
<!-- The name is passed to the method you want to use to store the data, which you make happen when the button is clicked by using the ngClick directive. -->
<input type="submit" ng-click="submitForm(name)" value="Click me!">
</form>
<p>Hello {{name}}!</p>
<!-- This bit of code is to display the results of adding names to the array in the browser window: -->
<pre>{{ data }}</pre>
</body>
Here's the Javascript:
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.name = "Name";
// I put the data array in the $scope so it can be displayed in the browser window and you can see the results:
$scope.data = [];
// Now, whenever the button is clicked, this method is run.
// It then stores the name in the 'data' array defined above.
$scope.submitForm = function(name) {
$scope.data.push(name);
};
});
Try this for it to show straight after typing:
<body ng-controller="myApp">
<input type="text" ng-model="name">
<p>Hello {{name}}!</p>
</body>
Javascript:
var myApp = angular.module('myApp',[]);
myApp.controller('myApp', function ($scope) {
$scope.name = $scope.name;
console.log($scope.name)
});
Small little JSFiddle for this:
https://jsfiddle.net/joshdmiller/HB7LU/

AngularJS forms for object with subobjects

How come subobjects do not get the two-way binding:
<!DOCTYPE html>
<html ng-app="app">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.1/angular.min.js"></script>
<script>
angular.module('app', []).controller('testCtrl', function($scope) {
$scope.doc = { "foo": "bar", "baz": { "zab": "rab" }}
})
</script>
</head>
<body>
<form ng-controller="testCtrl">
<label><span>Foo</span><input ng-model="doc.foo"></label>
<fieldset>
<legend>Baz</legend>
<label ng-repeat="(key,val) in doc.baz">
<span>{{key}}</span><input ng-model="val">
</label>
</fieldset>
<pre><code>{{doc | json}}</code></pre>
</form>
</body>
</html>
If I edit the foo, I can see it update. But if I edit the zab, I cannot see any changes.
Is there some way to make this work, and if not, another data construct (like baz being an array of objects) which could be made to work?
Change ng-model to this:
<span>{{key}}</span><input ng-model="doc.baz[key]">
The reason that val isn't updating your outer scope (testCtrl's scope) is that ng-repeat creates a new scope for each iteration - so you are only binding the input box to the local (iteration's) scope copy of val, not the parent's scope part of your larger object.

Resources