I am new to Angular JS, and I am learning it through the tutorials,
my question is why my model is not updating the view?
Following is the code.
<!DOCTYPE html>
<div ng-controller="MyContr">
{{xxx}}
</div>
<input type="text" ng-model="xxx" ng-controller="MyContr" />
<script>
var app = angular
.module("MyApp", [])
.controller("MyContr", function ($scope) {
var xxx="Alexander"
$scope.xxx = xxx;
});
</script>
According to the code shown on the question, It seems that your are calling MyContr twice,
one here:
<div ng-controller="MyContr">
{{xxx}} <!-- xxx (instance 1) -->
</div>
and another here:
<!-- xxx (instance 2) -->
<input type="text" ng-model="xxx" ng-controller="MyContr" />
... so two (different) instances of the same controller are being created. This way each instance have two different xxx var, each one has its own xxx variable on its scope.
Solution
Option 1 - You can share the data between instances (see Share data between AngularJS controllers and AngularJS: How can I pass variables between controllers?)
Option 2 - Enclose both html elements inside the same instance of the MyContr like this:
<span ng-controller="MyContr">
<div>
{{xxx}}
</div>
<input type="text" ng-model="xxx" />
</span>
Related
I am looking for a solution on passing data from a specific input text field to AngularJS. it may be a Javascript variable too. If the variable is changed from inside a javascript code it is not updating on AngularJS side. If i take the same variable and in the text field add at least one character or modify something i see variable updating and everything working as it should.
I tried something with angular.element(document.getElementById('ControllerElementID')).scope().funct(); but still no luck. When i update at least one field from the keyboard, all text fields that are related to "ng-model="sig.sigBase6422"" are updating properly as it should. If i call this updates through a JavaScript function i see updates only on specific text field and no updates at all on ng-model happening. How to make it updating as simple as possible? Below i will post a small example. I was able to store data from variable to a external file and in AngularJS read it from file and use it. this is way too long, complicated and ridiculous. I am sure there should be a better way.
Thank you!
<script type="text/javascript">
function addtext1() {document.getElementById("myID1").value = "1111111111111111";}
function addtext2() {document.getElementById("myID2").value = "2222222222222222";}
</script>
<div>
<form action="#" name="FORM1">
<TEXTAREA NAME="sigData" ng-model="sig.sigBase6422" ROWS="10" COLS="20">String: </TEXTAREA>
</form><br>
<input type="text" name="myID1" id="myID1" ng-model="sig.sigBase6422" ><br>
<input type="text" name="myID2" id="myID2" ng-model="sig.sigBase6422" ><br>
<p>Value {{sig.sigBase6422}}!</p>
</div>
<!-- test field -->
Add text 1
Add text 2
Indeed if you want to use AngularJS for what it was created, you have to rewrite your code completely using directive or controller. You variables and functions accessible from the view should be attached to the $scope too.
var myApp = angular.module("myApp", []);
myApp.controller("myCtrl", function($scope){
$scope.addtext1 = function () {
$scope.sig.sigBase6422 += "1111111111111111";
};
$scope.addtext2 = function () {
$scope.sig.sigBase6422 += "2222222222222222";
};
$scope.sig = {
sigBase6422: ""
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<div ng-app="myApp" ng-controller="myCtrl">
<form action="#" name="FORM1">
<TEXTAREA ng-model="sig.sigBase6422" ROWS="10" COLS="20">String: </TEXTAREA>
</form><br/>
<input type="text" name="myID1" id="myID1" ng-model="sig.sigBase6422" /><br/>
<input type="text" name="myID2" id="myID2" ng-model="sig.sigBase6422" /><br/>
<p>Value {{sig.sigBase6422}}!</p>
<!-- test field -->
<button ng-click="addtext1()">Add text 1</button>
<button ng-click="addtext2()">Add text 2</button>
</div>
You seem to have misunderstood how angular works. What you're trying to do is not how angular works. What you're trying to do with native JavaScript can be done with angular. Angular can update dom and Dom updates angular as it's responsible for causing updates.... anyway without getting any deeper. You need to read more on how angular works and try sticl within the bounds of angular instead of mixing.
That being said :
Tigger change on the Dom element after you have updated its value. Or better yet get access to scope variable on the Dom and call a function in angular with the value you're and set they value from inside of a angular.
Use this code while updating the value.
pick the controller first using
var scope = angular.element(document.getElementById('yourControllerElementID')).scope();
scope.<variablename> = <your operation>;
then
scope.$apply();
the remaining thing will be taken care by Angular.
I have many elements in my HTML code that have their ngModel assignment defined as ng-model = "object.[something]".
For example:
<div class="form-group row" ng-model="object.askUser">
I do this to be clear of my purpose for these elements. My question is how do I access these element in my Javascript? Do I call $scope.object.askUser, $object.askUser, or something else? I had a hard time finding things on the web about this, most likely because I wasn't quite sure of the words to use in the search bar to describe what I am trying to do.
Inside your controller use $scope.object.askUser:
var app = angular.module('TestApp', []);
app.controller("testCtrl", function ($scope) {
$scope.someObject = {};
$scope.someObject.askUser = "Hello, world!";
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="TestApp">
<div ng-controller="testCtrl">
<input ng-model="someObject.askUser" />
</div>
</div>
Side note:
You use in your example <div> with ngModel.
ngModel Docs:
The ngModel directive binds an input,select, textarea (or custom form
control) to a property on the scope
If you want to one-way bind a model to a div use Angular Expression:
<div class="form-group row">
{{ object.askUser }}
</div>
I got this example from the W3Schools tutorial on AngularJS. I made a small change from binding the value of the checkbox span to using an expression. I figured that the todo list wouldn't update any more. But it still does. What causes the ng-repeat to fire just because I have added a todo item?
http://plnkr.co/edit/Kojz2ODWDS8dFDNzjYR5?p=preview
<!DOCTYPE html>
<html>
<script src= "http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<body ng-app="myApp" ng-controller="todoCtrl">
<h2>My Todo List</h2>
<form ng-submit="todoAdd()">
<input type="text" ng-model="todoInput" size="50" placeholder="Add New">
<input type="submit" value="Add New">
</form>
<br>
<div ng-repeat="x in todoList">
<input type="checkbox" ng-model="x.done"> <span>{{x.todoText}}</span>
</div>
<p><button ng-click="remove()">Remove marked</button></p>
<script>
var app = angular.module('myApp', []);
app.controller('todoCtrl', function($scope) {
$scope.todoList = [{todoText:'Clean House', done:false}];
$scope.todoAdd = function() {
$scope.todoList.push({todoText:$scope.todoInput, done:false});
$scope.todoInput = "";
};
$scope.remove = function() {
var oldList = $scope.todoList;
$scope.todoList = [];
angular.forEach(oldList, function(x) {
if (!x.done) $scope.todoList.push(x);
});
};
});
</script>
</body>
</html>
Clicking the Add New Button submits the corresponding form and by using ng-submit="todoAdd()" it will call this function. This in turn adds an entry to the todoList in your scope. As this array has been modified the angular digest cycle is triggered and the list is updated.
Some suggestions for your questions: First of all, you mean W3Schools, not the W3C (which is a standardization organization and normally is not doing tutorials, which is why I got curios - Also, you will find lots of reasons why not to use W3Schools when goolgin around or looking at meta). Also, if you compare to some other code, you should include it or at least link to it.
I found it by googling and it seems your only change is using <span>{{x.todoText}}</span> instead of <span ng-bind="x.todoText"></span>. There really is no difference in terms of the digest cycle here. The only difference is that by using {{}} it might at first be rendered as curly brackets in the browser window, before the variable is actually replaced. Thus, it is usually better to use ng-bind.
I have got a form where user will enter a name and click Next. What I want to do is that, when the user clicks Next, I want to alert the updated value of $scope.name inside toChat function, but initial value is alerted, which is James. How can I access the updated value inside angular function? I have some serious problems understanding sharing variables within AngularJs.
js
.controller('NewcontactCtrl', function($scope,$rootScope, $ionicHistory,$window) {
$scope.name='James';
$scope.myGoBack = function() {
$ionicHistory.goBack();
};
$scope.toChat = function() {
alert($scope.name);
};
})
html
<ion-view view-title="New contact">
<ion-nav-back-button>
</ion-nav-back-button>
<ion-nav-buttons side="primary">
<button class="button" ng-click="myGoBack()">
Cancel
</button>
</ion-nav-buttons>
<ion-nav-buttons side="secondary">
<button class="button" ng-click="toChat()" >
Next
</button>
</ion-nav-buttons>
<ion-content scroll="false" has-header="false" padding="true" >
<div class="list">
<label class="item item-input">
<input type="text" placeholder="Name" ng-model="name" />
</label>
<label class="item item-input">
<textarea placeholder="Notes" ng-model="notes" rows="10"></textarea>
</label>
</div>
</ion-content>
</ion-view>
Can anyone help ?
Please see: https://github.com/angular/angular.js/wiki/Understanding-Scopes
The most relevant part in the above:
Scope inheritance is normally straightforward, and you often don't even need to know it is happening... until you try 2-way data binding (i.e., form elements, ng-model) to a primitive (e.g., number, string, boolean) defined on the parent scope from inside the child scope. It doesn't work the way most people expect it should work. What happens is that the child scope gets its own property that hides/shadows the parent property of the same name. This is not something AngularJS is doing – this is how JavaScript prototypal inheritance works. New AngularJS developers often do not realize that ng-repeat, ng-switch, ng-view and ng-include all create new child scopes, so the problem often shows up when these directives are involved. ...
This issue with primitives can be easily avoided by following the "best practice" of always have a '.' in your ng-models – watch 3 minutes worth. Misko demonstrates the primitive binding issue with ng-switch.
Having a '.' in your models will ensure that prototypal inheritance is in play. So, use
<input type="text" ng-model="someObj.prop1"> rather than
<input type="text" ng-model="prop1">.
I believe you have a directive in there somewhere (probably ion-content) that is creating a new scope where your input field is, separated from the scope where your Next button is.
To simulate this, I've used ng-repeat in the below snippet (but I'm repeating only once), which causes the same behaviour of splitting the scopes. If you were to use your controller code unmodified with this html, you'd reproduce the issue you're experiencing.
The solution around this is to 'use a dot (.)' when binding. Notice that I've wrapped the name within an object called 'data' on the scope, so now you refer to this as data.name instead of just name.
(function() {
'use strict';
angular.module('myApp', [])
.controller('NewcontactCtrl', function($scope, $window) {
$scope.repeaterTest = [1];
$scope.data = {name: 'James'};
$scope.toChat = function() {
$window.alert($scope.data.name);
};
});
})();
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.28/angular.min.js"></script>
<div ng-app="myApp">
<div ng-controller="NewcontactCtrl">
<label ng-repeat="test in repeaterTest">
<input type="text" placeholder="Name" ng-model="data.name" />
</label>
<button class="button" ng-click="toChat()">
Next
</button>
</div>
</div>
I think you need to alert something similar to...
alert($scope.name)
Addition to #Paul Fitzgerald, points, ensure that ng-controller="NewcontactCtrl" is included at the top scope in HTML DOM.
try adding a service in order to share data within scopes
.controller('NewcontactCtrl', function($scope,$rootScope,sharedData $ionicHistory,$window) {
$scope.name=sharedData.Name ;
$scope.myGoBack = function() {
$ionicHistory.goBack();
};
$scope.toChat = function() {
alert(sharedData.Name);
};
});
app.factory('sharedData', [function () {
var self = {};
self.Name = "James";
return self;
}]);
Here I took from this tutorial:
http://egghead.io/lessons/angularjs-the-dot
<!DOCTYPE html>
<html>
<head>
<title>AngularJS Tutorials</title>
<link rel="stylesheet" href="vendor/foundation/foundation.min.css">
</head>
<body>
<div ng-app="">
<input type="text" ng-model="data.message">
<h1>{{data.message}}</h1>
<div ng-controller="FirstCtrl">
<input type="text" ng-model="data.message">
<h1>{{data.message}}</h1>
</div>
<div ng-controller="SecondCtrl">
<input type="text" ng-model="data.message">
<h1>{{data.message}}</h1>
</div>
</div>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.3/angular.min.js"></script>
<script type="text/javascript" src="main.js"></script>
</body>
</html>
Main.js
function FirstCtrl($scope){
}
function SecondCtrl($scope){
}
Now load the page. If I try entering data in first input field, it updates all h1 tags and other input fields.
Same happends when entering data in 2nd or 3rd input field.
Now if we refresh the page and first enter data in 2nd input field
then it updates only 2nd h1 tag. Which I don't like - its different result of same code. Why it depends on users actions which he done first? This could cause lot of bugs.
This is because the variable data is not defined anywhere in the scope and it gets created at the top-most scope where you first edit it.
Contrast that example with this: http://plnkr.co/edit/mqtPaMsH2xVMJaW3mEkX?p=preview
Here, the controllers are:
function FirstCtrl($scope){
}
function SecondCtrl($scope){
}
function RootCtrl($scope) {
$scope.data = {};
}
And the template is:
<div ng-controller="RootCtrl">
<input type="text" ng-model="data.message" />
<h1>{{data.message}}</h1>
<div ng-controller="FirstCtrl">
<input type="text" ng-model="data.message" />
<h1>{{data.message}}</h1>
</div>
<div ng-controller="SecondCtrl">
<input type="text" ng-model="data.message" />
<h1>{{data.message}}</h1>
</div>
</div>
Here, since I explicitly define the data variable on the top-most scope, it is no longer created on the scopes for FirstCtrl or SecondCtrl. However, if I omit the definition $scope.data = {} on the RootCtrl, it'll be created on the fly and on the topmost scope which needs it defined and not necessarily on the RootCtrl's scope. If you then edit data.message on the RootCtrl's scope, it'll be re-created and inherited by any scopes which do not have it.
Look at the developer guides on GitHub for a more detailed explanation about inheritance of scope. Among controllers.
This is scope inheritance behavior. When angular encounters a ng-controller, it will create a new scope, inheriting from the current scope.
In your example, there are FirstCtrl's scope and SecondCtrl's scope, both inherit from rootScope and are isolated from each other.
If I try entering data in first input field, it updates all h1 tags
and other input fields.
In this case, it will create/update data.message on the rootScope (as it's not inside a ng-controller), which is inherited by FirstCtrl's scope and SecondCtrl's scope because in your code, data.message does not exist in FirstCtrl's scope and SecondCtrl's scope.
Now if we refresh the page and first enter data in 2nd input field
then it updates only 2nd h1 tag.
In this case, it will create/update data.message on the FirstCtrl's scope. rootScope and SecondCtrl's scope are not aware of this update.