i need an alternative solution for ng-change - angularjs

i tried calling the values using ng-change between two different ng-models. it works.
but the data is parsed to the other ng-model only if the data is changed, is there any alternate solution where i can have the data in both ng-models before changing data
I tried something like this
HTML
<input ng-model="customer.name" ng-change='tripsheet.customer_name=customer.name;'>
<input ng-model="tripsheet.customer_name" type="text" class="form-control input-lg" placeholder="Customer Name">
JS
$scope.customer = {
name:$scope.customers[$scope.whichItem].name,
address:$scope.customers[$scope.whichItem].address,
phone:$scope.customers[$scope.whichItem].phone
}
i want the routeParams data in both the above ng-models.

With something like this in your controller?
$scope.customer = {
name: "Tom"
};
$scope.tripsheet = {
customer_name: $scope.customer.name
}
Plunker

#mainguy's answer is a very good approach.
Or alternatively you can go with $watch instead of ng-change.
initialize a watcher for the model object
$scope.$watch('customer.name', customerNameChanged);
and define the function
function customerNameChanged() {
if(!$scope.tripsheet)
$scope.tripsheet = {};
$scope.tripsheet.customer_name = $scope.customer.name
}
ng-change triggers only when there is a user interaction and the data is changed.
$watch is triggered when the model object is changed programmatically and also when they’re being defined the first time

Related

angular $scope digest update from a dom event

I have an angular $scope variable that gets instantiated through a window event. The $scope variable is displayed correctly to the user, but updates are not being set through ng-model. What's odd is that ng-change has the correct value that I can use to manually set the scope variable.
I really don't understand why this is happening.
Event Handler:
document.addEventListener('updateSearchBar', handleUpdate);
function handleUpdate(eventData) {
$scope.benefitsFromDate = eventData.detail.fromDate;
$scope.$apply();
}
Front end:
<input
type="date"
name="fromDate"
ng-change="updateBenefitsFromDate(benefitsFromDate)"
ng-model="benefitsFromDate"
/>
<input
type="button"
value="Search"
class="btn btn-default"
ng-click="searchDocuments()"
ng-disabled="isSearchingDocuments"
/>
Angular snippet:
$scope.updateBenefitsFromDate = function(change) {
console.log($scope.benefitsFromDate); //still has old value
console.log(change); //has updated value when param is the $scope variable
//$scope.benefitsFromDate = change; //only way to update
};
$scope.searchDocuments = function() {
//ng-model never updates the variable when the value is changed and uses the instantiated value
console.log($scope.benefitsFromDate);
};
Why doesn't ng-model reflect the change, but passing $scope.benefitsFromDate in the ng-change function have the updated value?
I use the $timeout module when processing these kind of updates and avoid the call to $scope.$apply().
$timeout(function() {
$scope.benefitsFromDate = eventData.detail.fromDate;
});
I learned that angular is finicky about "dot rules".
All I had to do was prefix my data values with something else.
$scope.data = {};
$scope.data.benefitsFromDate = ...;
Or you can declare your controller to use as
ng-controller="appController as vm"

Angularjs conditional binding

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

angularjs ng-paste not updating model value

I have used ng-paste for textarea while pasting the link in textarea, i am calling a custom function to store that value. Please refer following code
<textarea rows="1" ng-model="myObj.content"
ng-paste="getContent(myObj)">
</textarea>
$scope.getContent = function(a){
console.log(a.content);
}
But in console always I am getting undefined value. How can I get my object value?
Passing model to function does not really make sense since you have already specified ng-model, so it's value will be updated as user types something into the textbox. If you want to track changes you can setup a $watch for your model or specify a function using ng-change.
If you want to know what user pasted, then that's another story. Handling ng-paste can be tricky. To access the actual event, easiest is to include jQuery before angularjs and then do e.g. following:
HTML template
<textarea rows="3"
placeholder="copy/paste here..."
ng-init="content = null"
ng-model="content"
ng-paste="paste($event.originalEvent)">
</textarea>
Controller
$scope.paste = function (event) {
var item = event.clipboardData.items[0];
item.getAsString(function (data) {
console.log(data);
});
};
Related plunker here http://plnkr.co/edit/ea5y5j
Simply use $timeout to call your paste callback after the model has been updated.
$scope.getContent = function(a){
$timeout(function () {console.log(a.content)});
}

Two-way bind does not work if the model is something like ng-model="record.name" for Kendo UI controls

I have a problem with Kendo UI controls
My HTML
<input type="text" ng-model="record.name" kendo-numeric-text-box />
<input type="text" ng-model="record.name"> </input>
<button ng-click="resetRecord()" >test bind</button>
My test.js
$scope.record ={};
$scope.resetRecord= function(){
$scope.record = {};
}
Well, when I execute the function resetRecord just the standard input clear, the kendo ui input does not clear, I've tried $scope.record =null and it does not work either.
if I change to code below, it works, but I need it works like above
$scope.resetRecord= function(){
$scope.record. name = null;
}
it happens with all input Kendo UI, not just kendo-numeric-text-box
if there is a way to iterate with record object, discovering all the "properties", such as name it will work for me.
My intention is just have one controller for all CRUD screen of the system, I wouldn't like to write one controller with model definition for each entity of the system.
is it a bug?
UPDATED - SOLVED
Solution 1
As runTarm said in solution 2.
for (prop in $scope.model.record) {
$scope.model.record[prop]='';
}
Solution 2
Just add the attribute k-rebind to the Kendo UI controls and it will update it's content according ng-model.
input type="text" ng-model="record.name" k-rebind="record.name" kendo-numeric-text-box />
This is not a bug, but a common issue due to the Prototypal Inheritance characteristic of JavaScript Object. I would recommend reading Understanding-Scopes for more detail.
You could avoid the problem by storing the record in another object, instead of in $scope directly. For example:
$scope.model = {};
$scope.model.record = {};
$scope.resetRecord = function() {
$scope.model.record = {};
}
Also change your ng-model:
<input type="text" ng-model="model.record.name" kendo-numeric-text-box />
<input type="text" ng-model="model.record.name"> </input>
<button ng-click="resetRecord()" >test bind</button>
Or if you wouldn't want to add the extra model., an alternative solution is what you have mentioned.
You could iterate over object's properties and delete them all like this:
for (prop in $scope.record) {
delete $scope.record[prop];
}
Hope this helps.

AngularJS calculated ng-model

I have following controller.
app.controller("testCtrl", function(){
$scope.utcTime = 1380150771;
$scope.parseTime = function(t){
//return local time string
}
});
In the view, I have
<input type="text" ng-model="parseTime(utcTime)" />
Its not working. Can I bind ng-model to a method that returns the string ?
Any alternative way to show the value in the input button ?
You can use ngChange and ngModel both
JS
$scope.utcTime = 1380150771;
$scope.parseTime = function(){
console.log($scope.utcTime);
//return local time string
}
HTML
<input type="text" ng-change="parseTime()" ng-model="utcTime" />
ng-model is mapping through tag and controller.
At first you can see default utcTime (1380150771) that you assign in input tag.
And when you change the text in input tag, ng-model(utcTime) will be changed automatically in the controller.
Then each letter that you typed will call ng-change(parseTime) function.
You can check by console.log method.
My solution is based on this source:
https://groups.google.com/forum/#!topic/angular/1mnra0vamtg
I have edited the Plunker sample code to use ng-value to generate and update ng-model using calculation function. See this link below:
http://plnkr.co/edit/Fmqw0wp37Ndk1yuWvFkV?p=preview
Also, the above sample shows you how you format the result for display using custom filter.
In other posts, some have suggested using $watch() to detect change to input variables and update ng-model variable accordingly. Using ng-value is much better than using $watch() since the latter forces you to include all input variables in the watch which may be impossible if you have very complex calculation model.
Tarek
Try doing this
app.controller("testCtrl", function(){
$scope.utcTime = 1380150771;
$scope.result= $scope.parseTime( $scope.utcTime)
$scope.parseTime = function(t){
//return local time string
}
});
html
<input type="text" ng-model="result" />
Yes you can try follwing:
its working example:
<input type="text" ng-model="parseTime(utcTime)" />
app.controller("testCtrl", function(){
$scope.utcTime = 1380150771;
$scope.parseTime = function(t){
//return local time string
new Date(t).toISOString();
}
});

Resources