angularjs ng-paste not updating model value - angularjs

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)});
}

Related

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

Why I cannot access form angular's properites in JS such as $error?

I cannot access angular's Form members. I don't have a clue why. I'm using angular 1.4. The full code is at: http://jsbin.com/lujojiduru/edit?html,js,console,output
angular.module('test',[]).controller('testController', function($scope){
$scope.sendInvitations = function(){
var error = myForm.NewInvitations.$error;
console.log('sent');
console.log('value: ' + error );
};
});
the value of $error is always undefined. Any idea?
var error = myForm.NewInvitations.$error;
should be:
var error = $scope.myForm.NewInvitations.$error;
Notice the $scope
This is assuming you have the name="myForm" on your <form> tag
So something like:
<div ng-controller="testController">
<form name="myForm" novalidate>
...
</form>
</div>
you can also, if you prefer, send in the validity of your form, to your method on the controller.
So:
<button class="btn btn-success" ng-click="sendInvitations(myForm.$valid)">Send Invitations</button>
And in your controller:
$scope.sendInvitations = function(isValid){
if(!isValid)
return;
};
Update
You also don't have any errors.
Add required to your input.
So your controller is now:
angular.module('test',[]).controller('testController', function($scope){
$scope.sendInvitations = function(){
debugger;//
var error = $scope.myForm.NewInvitations.$error;
console.log('sent');
console.log(error );
};
});
and your input
<input style="width: 95%" name="NewInvitations" type="email" ng-model="newInvitations" required />
This is an update to your bin
http://jsbin.com/hebikucanu/1/edit?html,js,console,output
myForm is not accessible in the global scope. You can pass it in as an argument to sendInvitations.
ng-click="sendInvitations(myForm)
$scope.sendInvitations = function(myForm){
It's unlikely that you'd need to do this, though. You can do use the myForm properties in the view.
In angular, you should never touch the DOM. Meaning, you should never invoke HTML elements directly as you would in traditional HTML/JS settings. (read more)
Angular encourages the use of ng-model to employ two-way binding as a means to communicate between the controller and the view. (angular two-way data binding tutorial)
Thus, the first change you should attempt is to replace
var error = myForm.NewInvitations.$error;
with:
var error = $scope.NewInvitations;
This will cause the code to run.
But it appears that you want to retrieve the email input validation error and display it through angular.
Here is an excellent explanation with a tutorial that I think achieves what you're trying to do. If you just want to see the code in action, try this link. (Be sure to hit the Run button.)
Hope this helps!

i need an alternative solution for ng-change

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

AngularJs can't access form object in controller ($scope)

I am using bootstrap-ui more specifically modal windows. And I have a form in a modal, what I want is to instantiate form validation object. So basically I am doing this:
<form name="form">
<div class="form-group">
<label for="answer_rows">Answer rows:</label>
<textarea name="answer_rows" ng-model="question.answer_rows"></textarea>
</div>
</form>
<pre>
{{form | json}}
</pre
I can see form object in the html file without no problem, however if I want to access the form validation object from controller. It just outputs me empty object. Here is controller example:
.controller('EditQuestionCtrl', function ($scope, $modalInstance) {
$scope.question = {};
$scope.form = {};
$scope.update = function () {
console.log($scope.form); //empty object
console.log($scope.question); // can see form input
};
});
What might be the reasons that I can't access $scope.form from controller ?
Just for those who are not using $scope, but rather this, in their controller, you'll have to add the controller alias preceding the name of the form. For example:
<div ng-controller="ClientsController as clients">
<form name="clients.something">
</form>
</div>
and then on the controller:
app.controller('ClientsController', function() {
// setting $setPristine()
this.something.$setPristine();
};
Hope it also contributes to the overall set of answers.
The normal way if ng-controller is a parent of the form element:
please remove this line:
$scope.form = {};
If angular sets the form to your controllers $scope you overwrite it with an empty object.
As the OP stated that is not the case here. He is using $modal.open, so the controller is not the parent of the form. I don't know a nice solution. But this problem can be hacked:
<form name="form" ng-init="setFormScope(this)">
...
and in your controller:
$scope.setFormScope= function(scope){
this.formScope = scope;
}
and later in your update function:
$scope.update = function () {
console.log(this.formScope.form);
};
Look at the source code of the 'modal' of angular ui bootstrap, you will see the directive has
transclude: true
This means the modal window will create a new child scope whose parent here is the controller $scope, as the sibling of the directive scope. Then the 'form' can only be access by the newly created child scope.
One solution is define a var in the controller scope like
$scope.forms = {};
Then for the form name, we use something like forms.formName1. This way we could still access it from our controller by just call $scope.forms.formName1.
This works because the inheritance mechanism in JS is prototype chain. When child scope tries to create the forms.formName1, it first tries to find the forms object in its own scope which definitely does not have it since it is created on the fly. Then it will try to find it from the parent(up to the prototype chain) and here since we have it defined in the controller scope, it uses this 'forms' object we created to define the variable formName1. As a result we could still use it in our controller to do our stuff like:
if($scope.forms.formName1.$valid){
//if form is valid
}
More about transclusion, look at the below Misco's video from 45 min. (this is probably the most accurate explanation of what transcluded scopes are that I've ever found !!!)
www.youtube.com/watch?v=WqmeI5fZcho
No need for the ng-init trickery, because the issue is that $scope.form is not set when the controller code is run. Remove the form = {} initialization and get access to the form using a watch:
$scope.$watch('form', function(form) {
...
});
I use the documented approach.
https://docs.angularjs.org/guide/forms
so, user the form name, on "save" click for example just pass the formName as a parameter and hey presto form available in save method (where formScopeObject is greated based upon the ng-models specifications you set in your form OR if you are editing this would be the object storing the item being edited i.e. a user account)
<form name="formExample" novalidate>
<!-- some form stuff here -->
Name
<input type="text" name="aField" ng-model="aField" required="" />
<br /><br />
<input type="button" ng-click="Save(formExample,formScopeObject)" />
</form>
To expand on the answer by user1338062: A solution I have used multiple times to initialize something in my controller but had to wait until it was actually available to use:
var myVarWatch = $scope.$watch("myVar", function(){
if(myVar){
//do whatever init you need to
myVarWatch(); //make sure you call this to remove the watch
}
});
For those using Angular 1.5, my solution was $watching the form on the $postlink stage:
$postLink() {
this.$scope.$watch(() => this.$scope.form.$valid, () => {
});
}

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