Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot get textarea value in angularjs

Here is my plnkr: http://plnkr.co/edit/n8cRXwIpHJw3jUpL8PX5?p=preview You have to click on a li element and the form will appear. Enter a random string and hit 'add notice'. Instead of the textarea text you will get undefined.

Markup:

<ul>     <li ng-repeat="ticket in tickets" ng-click="select(ticket)">          {{ ticket.text }}     </li> </ul> <div ui-if="selectedTicket != null">      <form ng-submit="createNotice(selectedTicket)">         <textarea ng-model="noticeText"></textarea>         <button type="submit">add notice</button>     </form> </div> 

JS part:

$scope.createNotice = function(ticket){    alert($scope.noticeText); } 

returns 'undefined'. I noticed that this does not work when using ui-if of angular-ui. Any ideas why this does not work? How to fix it?

like image 748
UpCat Avatar asked Apr 29 '13 17:04

UpCat


People also ask

How to get a value of textarea?

We can get the value of textarea in jQuery with the help of val() method . The val() method is used to get the values from the elements such as textarea, input and select. This method simply returns or sets the value attribute of the selected elements and is mostly used with the form elements.

How to get input from textarea?

Use the value property to get the value of a textarea, e.g. const value = textarea. value . The value property can be used to read and set the value of a textarea element. If the textarea is empty, an empty string is returned.

How to get selected value from textarea in JavaScript?

How to get selected text of Textarea in JavaScript ? var selectedText=document. getElementById("editor"). getSelectedText();

What is textarea in angular?

They provide data-binding, which means they are part of the AngularJS model, and can be referred to, and updated, both in AngularJS functions and in the DOM. They provide validation. Example: an <textarea> element with a required attribute, has the $valid state set to false as long as it is empty.


2 Answers

Your problem lies in the ui-if part. Angular-ui creates a new scope for anything within that directive so in order to access the parent scope, you must do something like this:

<textarea ng-model="$parent.noticeText"></textarea> 

Instead of

<textarea ng-model="noticeText"></textarea> 
like image 172
Mathew Berg Avatar answered Sep 18 '22 07:09

Mathew Berg


This issue happened to me while not using the ng-if directive on elements surrounding the textarea element. While the solution of Mathew is correct, the reason seems to be another. Searching for that issue points to this post, so I decided to share this.

If you look at the AngularJS documentation here https://docs.angularjs.org/api/ng/directive/textarea , you can see that Angular adds its own directive called <textarea> that "overrides" the default HTML textarea element. This is the new scope that causes the whole mess.

If you have a variable like

$scope.myText = 'Dummy text'; 

in your controller and bind that to the textarea element like this

<textarea ng-model="myText"></textarea> 

AngularJS will look for that variable in the scope of the directive. It is not there and thus he walks down to $parent. The variable is present there and the text is inserted into the textarea. When changing the text in the textarea, Angular does NOT change the parent's variable. Instead it creates a new variable in the directive's scope and thus the original variable is not updated. If you bind the textarea to the parent's variable, as suggested by Mathew, Angular will always bind to the correct variable and the issue is gone.

<textarea ng-model="$parent.myText"></textarea> 

Hope this will clear things up for other people coming to this question and and think "WTF, I am not using ng-if or any other directive in my case!" like I did when I first landed here ;)

Update: Use controller-as syntax

Wanted to add this long before but didn't find time to do it. This is the modern style of building controllers and should be used instead of the $parent stuff above. Read on to find out how and why.

Since AngularJS 1.2 there is the ability to reference the controller object directly instead of using the $scope object. This may be achieved by using this syntax in HTML markup:

<div ng-controller="MyController as myc"> [...] </div> 

Popular routing modules (i.e. UI Router) provide similar properties for their states. For UI Router you use the following in your state definition:

[...] controller: "MyController", controllerAs: "myc", [...] 

This helps us to circumvent the problem with nested or incorrectly addressed scopes. The above example would be constructed this way. First the JavaScript part. Straight forward, you simple do not use the $scope reference to set your text, just use this to attach the property directly to the controller object.

angular.module('myApp').controller('MyController', function () {     this.myText = 'Dummy text'; }); 

The markup for the textarea with controller-as syntax would look like this:

<textarea ng-model="myc.myText"></textarea> 

This is the most efficient way to do things like this today, because it solves the problem with nested scopes making us count how many layers deep we are at a certain point. Using multiple nested directives inside elements with an ng-controller directive could have lead to something like this when using the old way of referencing scopes. And no one really wants to do that all day!

<textarea ng-model="$parent.$parent.$parent.$parent.myText"></textarea> 
like image 41
marandus Avatar answered Sep 22 '22 07:09

marandus