What causes AngularJS variable change to fire html update? - javascript

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.

Related

make javascript variable update live with text input

hey this is an edited version of my first post:
Pretty much what I want to do is have a text input box that stores its contents in a javascript variable. The catch is I want it to happen live, so the variable will update automatically say, ever .2 seconds without the user needing to press a submit button. Thanks
Are you looking for the two way data binding? Something like this: https://codepen.io/manishiitg/embed/ZYOmbB?
<html>
<head>
<script src="https://code.angularjs.org/1.3.8/angular.min.js"></script>
<script>
var mainMod = angular.module('MainApp', []);
mainMod.controller('MainCtrl', function ($scope) {
$scope.text = '';
});
</script>
</head>
<body ng-app='MainApp'>
<div ng-controller='MainCtrl'>
<div>
Change Text Here:
<input type='text' ng-model='text' />
</div>
<div>
<p>Text: {{text}}</p>
</div>
</div>
</body>
<html>
You can achieve that with Angular, React and Vue.js framework, even with jQuery. Perhaps you should try one of the frameworks that solves your needs quickly.
If you choose Angular, I recommend you to make the tutorial steps, specially this part: https://angular.io/tutorial/toh-pt1#two-way-binding

AngularJS on JSFiddle

I'm new AngularJS, I'm trying to test the most basic form using AngularJS in JSFiddle. I'm not sure if I forget to configure anything in JSFiddle, but it is not working and it should.
I followed a basic sample from here.
I also include the CDN from here.
Here is the Angular code:
var app = angular.module('myApp', []);
app.controller('formCtrl', function($scope) {
$scope.firstname = "John";
});
Link to my Fiddle: http://jsfiddle.net/bheng/tth4guev/
Settings
include
How would one go about debugging this further?
There are two things missing
(i) You need to add ng-app directive as follows,
<div ng-app="myApp" ng-controller="formCtrl">
(ii) Change the angular.js script version above 1.1 to use without a global controller, and change load type as No wrap in <head>
WORKING FIDDLE
I see, you did not add a name to your controller,and Angular App but in the JS you are accessing 'formctrl'. Go ahead and add a div around the form and add a ng-app='myApp' and a ng-controller='form-ctrl' to your form and it should work.
You need to wrap the form tag in a div tag with ng-app attribute. Your h1 tag should be encapsulated within the div tag as well...
Here's a working example:
<div ng-app="">
<form>
First Name: <input type="text" ng-model="firstname">
</form>
<h1>You entered: {{firstname}}</h1>
</div>
So here's the thing I saw with your code:
You need to add the name of the App and the controller to the div.
Also you are repeating the name of the person in both fields, if you wish you can make an object with the person information to access each of his data fields:
<div ng-app="myApp" ng-controller="formCtrl">
<form>
Email: <input type="text" ng-model="person.firstname" />
Password: <input type="text" ng-model="person.password" />
</form>
<h1>You entered: {{ person.firstname }}</h1>
</div>
<script>
var myApp = angular
.module("myApp",[])
.controller("formCtrl", function($scope) {
//here's the object called "person":
var person = {
firstname: "John",
password: "password"
};
$scope.person = person;
});
</script>

AngularJS passing data to Javascript variables and opposite

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.

Update input value

I am building a drum machine using AngularJS and having issues adjusting the tempo from the user interface.
I have got the object "this.tempo=120" & "<input class="bpm-input" type="number" onchange="updateBPM()" min="100" max="150" ng-model="$ctrl.tempo"></input>"
This doesn't seem to update the tempo value, only the value shown in the input box.
What function would I need to update the value within the controller?
It is normal, when you use AngularJS, you need to use the Angular WAY.
In other words, what angular do for you is the only way to do it.
AngularJS drastically control your DOM and use it as a copy.
If you change the DOM without the angular behavior, angular cannot update his copy and throws bad behaviors.
You need to use all Angular things, to tell him to apply his magic on your DOM.
Change your onclick attribute by ng-click angular directive, put your updateBPM into your controller scope, and this will works.
Hope that helps you!
Basic things you can do are as in the attached snippet also try having Angular patterns for a manageable code base and good performance Patterns
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<body>
<div ng-app="myApp" ng-controller="myController as myCtrl">
<input class="bpm-input" type="number" ng-change="myCtrl.updateBPM()" min="100" max="150" ng-model="myCtrl.tempo"></input>
</div>
<script>
var app = angular.module('myApp', []);
app.controller('myController', function($scope) {
var myCtrl = this;
myCtrl.tempo=120;
myCtrl.updateBPM = function(){
alert(myCtrl.tempo);
}
});
</script>
</body>
</html>
Code is attached below
<script>
var mainModule = angular.module('mainModule', [])
.controller('mainCntrl', function($scope) {
var vm = this;
vm.tempo = 120;
});
</script>
<div ng-app="mainModule">
<div ng-controller="mainCntrl as ctrl">
<input class="bpm-input" type="number" min="100" max="150" ng-model="ctrl.tempo"></input>
</div>
</div>

Dynamically add angular attributes to old html forms

I have a project where I'm currently trying to refactor an old system that was hinged on jquery from the ground up with angular 1.x. However, there are a lot of old HTML forms that I'd like to reuse the bulk of so I don't want to recreate them. I'd love it if there was a way to keep it purely angular, but I'm honestly at a loss of how I'd do that (or whether or not I can). I'm fairly new to angular so there are a lot of inner workings to it that I'm still not privy to.
I've searched around on google and other places including here and I can't really even find other people talking about it. That tells me that either I'm searching badly or it's something that I should probably not be working towards.
All the html pages have identically id'd fields so I feel I can reliably base things on that. For example: all forms with first name text boxes have an id of "cl_fname".
Is there anyway that I can accomplish: getting the form, adding an ng-model="cl_fname" or something to the relevant tag and then display the form? I've gotten to the point where I can get the html page, hold it in the scope and then display using ng-bind-html, but figuring out how to add angular attributes to specific elements I can't figure out.
You can achieve this with jQuery and the attr() method.
I created a plunker here that demonstrates adding angular to an existing "plain" html form.
In the example, I'm using id selectors, but you could use any combination of selectors to ensure you get the right elements.
The below is a quick code snippet from my Plunker example:
HTML:
<div ng-app="myApp">
<form id='myForm1' data-test="test2">
<span>First Name:</span>
<input type="text" id="myForm1_firstName" />
<input type="submit" id="myForm1_Submit" value="Go!" />
</form>
</div>
JS:
// set up angular
var myApp = angular.module('myApp', []);
myApp.controller('MyForm1Controller', ['$scope', function($scope) {
$scope.firstName = 'Angular Working!';
}]);
// use jQuery to add the relevent attributes to our form
var jqMyForm1 = $('form#myForm1');
var jqTxtFirstName = jqMyForm1.find('input[type="text"]#myForm1_firstName');
//add controller to form
jqMyForm1.attr('ng-controller', 'MyForm1Controller');
//bind the textbox to the angular 'firstName' variable
jqTxtFirstName.attr('ng-model', "firstName");
EDIT:
just realised you want to load the html form dynamically.
Version 2 of the plunker (here) will now dynamically load a HTML form from an external resource (separate html page), inject it into the current page, add the angular bindings to it, and then get angular to recognise it.
The key to getting angular to recognise the form is the use of the $compile object (angular $compile documentation).
Again, quick snippets of the code in use:
HTML (main page):
<div ng-app="myApp" ng-controller="LoadingController"></div>
HTML (myForm1.html):
<form id='myForm1' data-test="test2">
<span>First Name:</span>
<input type="text" id="myForm1_firstName" />
<input type="submit" id="myForm1_Submit" value="Go!" />
</form>
JS:
// set up angular
var myApp = angular.module('myApp', []);
// main controller for loading the dynamic form
myApp.controller('LoadingController', ['$scope','$http','$compile', function($scope,$http,$compile) {
$scope.loadHtmlForm = function(formURL) {
$http.get(formURL).then(function successCallback(response){
var jqForm = $(response.data);
var jqTxtFirstName = jqForm.find('input[type="text"]#myForm1_firstName');
//add controller to form
jqForm.attr('ng-controller', 'MyForm1Controller');
//bind the textbox to the angular 'firstName' variable
jqTxtFirstName.attr('ng-model', "firstName");
$('div').append(jqForm);
$compile(jqForm[0])($scope);
});
}
$scope.loadHtmlForm('myForm1.html');
}]);
// form controller for managing the data
myApp.controller('MyForm1Controller', ['$scope', function($scope) {
$scope.firstName = 'Angular Working!';
}]);

Categories

Resources