Looking at this fiddle which uses knockout and backbone, are these libraries being automatically imported ?
backbone and knockout fiddle
Code here :
Name: <input data-bind="value: name" type="text"/><br>
Age: <input data-bind="value: age" type="text"/><br>
Evil: <input type="checkbox" data-bind="checked: evil" /><br>
<button id="foo">Change Model!</button>
// create a plain old backbone model
var backboneModel = new Backbone.Model({
name: "Montgomery Burns",
age: 102,
evil: true
});
// use knockback.js to bridge knockout data-binding with backbone models
// read_only is set to false to make the binding two-way.
// note the use of the "kb" api for knockback.
var viewModel = kb.viewModel(backboneModel, {
read_only: false
});
// at this point, knockback has given us a viewModel which is compatible
// with the normal knockout api. so we can use the "ko" api now.
ko.applyBindings(viewModel);
$("#foo").click(function() {
backboneModel.set ({
"name": "Lisa Simpson",
"age": 8,
"evil": false
});
});
They've been included by the author of the fiddle using the Manage resources feature in the left sidebar.
Related
I am reading the book "Pro AngularJS" by Adam Freeman, Apress.
He creates an app that is a to-do list and you can add your own things on the list. In the part "Responding to User Interaction", page 34
Here is the model
var model = {
user: "Adam",
items: [{ action: "Buy Flowers", done: false },
{ action: "Get Shoes", done: false },
{ action: "Collect Tickets", done: true },
{ action: "Call Joe", done: false }]
};
the app
var todoApp = angular.module("todoApp", []);
the controller
todoApp.controller("ToDoCtrl", function ($scope) {
$scope.todo = model;
$scope.addNewItem = function (actionText) {
$scope.todo.items.push({ action: actionText, done: false });
}
});
the input field
<input class="form-control" ng-model="actionText" />
and the button that adds new things in the model
<button ng-click="addNewItem(actionText)">Add</button>
And then he comments this line <input class="form-control" ng-model="actionText" /> (pp 36)
I have specified the name of a property for the directive to update
that is not part of the model. The ng-model directive will dynamically
create the property for me within the scope of the controller,
effectively creating dynamic model properties that are used to handle
user input.
What does he mean by
creating dynamic model properties that are used to
handle user input.
?
Do we add a new property to the model named actionText ? . We add a ""pseudo""-property so the controller can use it to grab an input value?
If this is the case, then why use ng-model="actionText" and not just use plain old getElementById? After all we only need the value of the field.
Can something like ng-click getElementById("myInput").value do the trick and also avoid adding unwanted stuff to the model?
Thanks
One of the features of angularjs is to abstract as much as possible the manual javascript manipulation of the DOM.
Imagine having 10 fields on a form and having to do getElementById…..It’s much simpler in angularjs. You just need to have ng-model in each input type and on your controller methods you just use your model. You don't even have to pass them as arguments; the method on the controller will have access to the model.
I think that using ng-model will ultimately generate a cleaner code than using getElementById to access each field value.
create a form in angular 1.5
< form name="movieForm" ng-submit="addMovie(movie) ../>
and when I try to reset the form after form submission using
$scope.movieForm.$setPristine()
BUT it gives error in console : Cannot read property '$setPristine' of undefined
form.html
<form name="movieForm" novalidate role="form" ng-submit="movieForm.$valid && addMovie(movie)">
<input type="text" ng-model="movie.name" name="mName" required />
<input type="text" ng-model="movie.star" name="mStar" />
<input type="number" ng-model="movie.year" name="mYear" required />
<input type="submit" value="Save" />
<input type="button" value="Reset" ng-disabled="movieForm.$pristine" ng-click="reset()" />
</form>
app.js
(function() {
var app = angular.module('app', []);
app.controller('movieController', function($scope) {
$scope.title = "Home Page";
$scope.movieData = [{
name: 'PiKu',
star: 'Irrfan Khan',
releaseYear: '2015'
}];
$scope.addMovie = function(movie) {
if(movie && movie.name) {
$scope.movieData.push({
name : movie.name,
star : movie.star,
releaseYear : movie.year
});
}
};
$scope.reset = function() {
$scope.movieForm.$setPristine();
$scope.movieForm.$setUntouched();
};
// **un-commenting below line gives error in console**
//$scope.reset();
});
}());
also checked $scope.movieForm() in console but its undefined ?
What is the issue?
see the DEMO
You're trying to access $scope.movieForm before bindings actually initialized.
Edit
To be clear: $setPristine - not clears form fields. For clearing form fields you can just reset the object that form controls are bound to:
$scope.movie = {};
here's working demo
I think you are using $setPristine wrong.
"This method can be called to remove the 'ng-dirty' class and set the form to its pristine state (ng-pristine class). This method will also propagate to all the controls contained in this form."
So this only clears classes but not the $scope variables. You have to reset $scope.movie variable.
for example I added this default form variable
var defaultForm={
name: "",
star: "",
year: ""
}
and modified your reset code
$scope.reset = function() {
$scope.movie = angular.copy(defaultForm);
$scope.movieForm.$setPristine();
};
This works fine.
Check out the fiddle.
http://output.jsbin.com/hugiye/2
As per the angular docs $setPristine():
"This method can be called to remove the 'ng-dirty' class and set the form to its pristine state (ng-pristine class). This method will also propagate to all the controls contained in this form."
This only reset classes not the actual scope variable.
If you want to set scope variable to default state then you should reset scope variable too.
`
var movie = {
name: '',
star: '',
year: ''
};
and in your reset function you have to add this
$scope.movie = angular.copy(movie);
`
I have used angular's ng-model for quite some time which demonstrates two way data binding. What i want to accomplish is to bind only an input field to a model only if there are changes.
If I have
<input value="Hello world">
I want the value to be propagated to a model variable only if there are changes made to the value.
Answer would depend on event you want to use to update model.
Assuming you are wanting an "edit form " but don't want the master model to update live you can make a copy of the model and extend the master on "save"
Starting data:
$scope.item ={age: 25, name: 'Foo Bar'};
$scope.editItem = angular.copy($scope.item);
HTML
<input ng-model="editItem.age">
<button ng-click="updateItem()">Update</button>
Update function:
$scope.updateItem = function (){
$http.put(url, $scope.editItem).success(function(resp){
// merge data
angular.extend( $scope.item, $scope.editItem);
});
}
You could also do something similar using ng-change
You can do it with using of additional variable and $watch. Example:
<input type="search" ng-model="searchText">
And in controller
$scope.$watch('searchText', function() {
$scope.filterText = $scope.searchText;
});
So $scope.filterText will be changed to $scope.searchText value if any changes in input
I have a class called Case that contains a list of executionSteps. Each executionStep has a boolean property called enabled. I am trying to set in on the HTML side but it never gets updated on the JS side.
HTML side
<td>
<input type="checkbox"
ng-checked="acase.executionSteps[0].enabled"
ng-model="aa" ng-change="updateCaseExecutionStep('{{study.id}}','{{acase.id}}','{{acase.executionSteps[0].id}}','{{acase.executionSteps[0]}}')"/>
</td>`
On the controller side I have the function
updateCaseExecutionStep
defined as shown below
$scope.updateCaseExecutionStep = function(studyId,caseId,executionStepId,executionStep){
...
...
}
Problem is when I update my checkbox or even manually update the enabled property of the executionStep
$scope.updateCaseExecutionStep = function(studyId,caseId,executionStepId,executionStep){
executionStep.enabled = true;
...
}
I don't see any change. The enabled property of executionStep passed in the JS does not change. Please help.
Do I have to modify somehow on the The HTML side ?
You are trying to force too complex solution. To start with, you do not need ng-checked nor ng-change when you are using ng-model.
Let's say you have the following controller
app.controller('MainCtrl', function($scope) {
$scope.case = {
caseId: 0,
steps: [
{ id: 1, name: 'First step', enabled: true },
{ id: 2, name: 'Second step', enabled: false },
{ id: 2, name: 'Third step', enabled: false }]
};
});
And related HTML
<div ng-repeat="step in case.steps">
<input type="checkbox" ng-model="step.enabled"> {{ step.name }}
</div>
That's all it takes!
Example Plunk here http://plnkr.co/edit/QjD91l
Edit:
If you need to do some processing based on selection, then yes, you could add ng-change to input control. Then HTML becomes
<input type="checkbox" ng-model="step.enabled" ng-change="stateChanged(step)"> {{ step.name }}
And in controller
$scope.stateChanged = function(step){
console.log('Changed step id:' + step.id + ' enabled state to ' + step.enabled;
};
I had to abandon ng-model for my checkbox as it was not picking up the initial value that was set in the model (in response to a service call). All of the other input controls were responding correctly to the model (and, interestingly, were correctly enabled/disabled based on the value backing the checkbox).
Instead, I used the 'checked' attibute and ng-click, as so:
<input type="text" ng-disabled="!myModel.isFruit" ng-model="myModel.seedCount">
<input type="checkbox" checked="{{myModel.isFruit}}" ng-click="onFruitClicked()"> Is Fruit
In my controller:
$scope.myModel = {
isFruit : myServices.getIsFruit(),
seedCount : myServices.getSeedCount()
};
$scope.onFruitClicked = function() {
// toggle the value
$scope.myModel.isFruit = !$scope.myModel.isFruit;
// save the new value
myServices.setIsFruit($scope.myModel.isFruit);
};
Does angularjs watch/track the changes of the id property when it is not bound in the html?
JS
$scope = { firstname: "test1", lastname: "test2", id: 10};
HTML
<input type="text" ng-model="firstname" />
<input type="text" ng-model="lastname" />
Does angularjs watch/track the changes of the id property?
Not automatically. AFAIK, watches are created during the compile phase when angular is parsing through the DOM to understand what it needs to track. For example, if you define a controller in your module, but never use it with ng-controller in HTML, an instance of your controller will never be created. You can see how this is a good thing.
If you want to manually set up a watch for id, then use $scope.$watch to do so.
It does watch for two-way data-binding. However you should always use the .. This is because of prototypal inheritance. The <form> tag you've probably used introduced a new child scope and firstname/lastname would be overwritten in that case.
Do not use
<input ng-model="firstname"> <!-- NO -->
but use
<input ng-model="form.firstname"> <!-- YES -->
And in your controller, use $scope.form = { firstname: '...', lastname: '...', id: '...' };. Angular will watch for changes.
Watching for form.id
You could watch for the change of the id property with the following in your controller:
$scope.$watch('form.id', function(newVal, oldVal) {
// do something with changed value
});