2013-04-29 105 views
47

這是我的plnkr:http://plnkr.co/edit/n8cRXwIpHJw3jUpL8PX5?p=preview您必須單擊li元素並且將出現表單。輸入一個隨機字符串並點擊'添加通知'。而不是textarea文本,你會得到未定義。無法在angularjs中獲取textarea值

標記:

<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部分:

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

返回 '未定義'。我注意到這在使用UI時不起作用 - 如果使用角UI。任何想法,爲什麼這不起作用?如何解決它?

回答

86

你的問題在於ui-if部分。似乎角UI創建該指令中的任何一個新的範圍,從而以訪問父範圍,你必須做這樣的事情:

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

而不是

<textarea ng-model="noticeText"></textarea> 
58

此問題發生而不是在textarea元素周圍的元素上使用ng-if指令。雖然Mathew的解決方案是正確的,但理由似乎是另一回事。尋找這個問題指向這個職位,所以我決定分享這個。

如果您看一下這裏的AngularJS文檔https://docs.angularjs.org/api/ng/directive/textarea,您會發現Angular添加了自己的僞指令<textarea>,它「覆蓋」了默認的HTML textarea元素。這是導致整個混亂的新範圍。

如果你有一個像

$scope.myText = 'Dummy text'; 

一個變量在你的控制器,並綁定該到textarea元素這樣

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

AngularJS將尋找在指令範圍變量。它不在那裏,因此他走到了父母身邊。該變量出現在那裏,文本被插入到textarea中。更改textarea中的文字時,Angular不會更改父母的變量。相反,它會在指令的作用域中創建一個新變量,因此原始變量不會更新。如果您將textarea綁定到父變量,如Mathew所建議的那樣,Angular將始終綁定到正確的變量,問題就消失了。

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

希望這將清除的事情了其他人來這個問題,並認爲「跆拳道,我沒有使用NG-if或在我的情況下,任何其他指令!」像我一樣,當我第一次在這裏登陸;)

更新:使用控制器作爲語法

就想很久以前添加這個,但沒有找到時間去做。這是建築控制器的現代風格,應該用來代替上面的$parent。請繼續閱讀以找出如何爲什麼

由於AngularJS 1。2有能力直接引用控制器對象,而不是使用$scope對象。這可以通過在HTML標記使用此語法來實現:

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

熱門路由模塊(即UI路由器),用於它們的狀態提供相似的性質。對於UI路由器使用了下面在你的狀態定義:

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

這有助於我們與嵌套或不正確地處理範圍來規避這個問題。上面的例子將以這種方式構建。首先是JavaScript部分。直截了當地說,你簡單地不要使用$scope引用來設置你的文本,只需使用this將屬性直接附加到控制器對象。

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

用的標記爲textarea控制器的語法是這樣的:

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

這是做的事情是今天這個樣子是最有效的方式,因爲它解決了嵌套範圍問題使我們能夠計算出在某個特定點上我們有多少層。在使用舊的引用範圍方式時,在ng-controller指令的元素中使用多個嵌套指令可能會導致類似的情況。沒有人真的想整天這樣做!

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

大詳細的解釋!很有用! – Wolfgang 2015-06-29 12:21:55

+0

拯救了我的生命。感謝您的解釋! – NewestStackOverflowUser 2015-12-01 14:59:58

2

這的確是,ui-if創建的問題。 Angular if指令根據表達式銷燬並重新創建dom樹的某些部分。這是創建新的範圍,而不是marandus建議的textarea指令。

這裏有一篇關於ngIf和ngShow之間差異的文章,它描述了這一點 - what is the difference between ng-if and ng-show/ng-hide

23

綁定textarea的一個範圍變量的財產,而不是直接到範圍變量:

控制器:

$scope.notice = {text: ""} 

模板:

<textarea ng-model="notice.text"></textarea> 
+1

這在Angular 1.5中適用於我。奇怪的限制,我敢肯定,這曾經工作(回到1.3?)直接綁定到範圍變量... – robru 2016-03-01 20:33:31

+1

這種解決方案似乎比'$ parent.notice'好! – Paritosh 2016-03-13 07:21:56

+0

您的解決方案工作。任何解釋爲什麼直接綁定失敗? – Shivendra 2016-05-11 17:47:58