Mô hình Ng không cập nhật giá trị bộ điều khiển


270

Có lẽ là câu hỏi ngớ ngẩn, nhưng tôi có dạng html với đầu vào và nút đơn giản:

<input type="text" ng-model="searchText" />
<button ng-click="check()">Check!</button>
{{ searchText }}

Sau đó, trong bộ điều khiển (mẫu và bộ điều khiển được gọi từ routeProvider):

$scope.check = function () {
    console.log($scope.searchText);
}

Tại sao tôi thấy chế độ xem được cập nhật chính xác nhưng không được xác định trong bảng điều khiển khi nhấp vào nút?

Cảm ơn!

Cập nhật: Có vẻ như tôi đã thực sự giải quyết vấn đề đó (trước đây phải đưa ra một số cách giải quyết) với: Chỉ phải thay đổi tên tài sản của tôi từ searchTextthành search.text, sau đó xác định $scope.search = {};đối tượng trống trong bộ điều khiển và voila ... Không biết tại sao nó hoạt động Tuy nhiên ;]


bạn có chắc là bạn đang sử dụng bộ điều khiển này trong phần này của tài liệu không? bạn có thể gửi một ví dụ thất bại tối thiểu?
wroniasty

1
Có, chắc chắn 100% bộ điều khiển vẫn ổn, vấn đề đó dường như quen thuộc với tôi ... Đáng ngạc nhiên là nó hoạt động khi tôi thay đổi tên thuộc tính từ searchTextsang search.text, bất kỳ ý tưởng nào tại sao ??
giả kim

4
@Arthur: Điều đó không rõ ràng nhưng mô hình ng chỉ tạo ra một loại biến cục bộ nói trong chế độ xem của bạn, vì vậy nếu bạn muốn giữ nó theo cách này, bạn sẽ cần chuyển nó vào hàm check (), như: check ( searchText) và bộ điều khiển của bạn sẽ nhận ra nó sau đó. Hy vọng nó sẽ giúp
giả kim

3
Đối với hồ sơ, nó đánh vần voila, không vuala, wollavv
Dan Bechard

3
Tôi nghĩ rằng câu trả lời bạn đang tìm kiếm là tại stackoverflow.com/a/14049482/1217913
Willa

Câu trả lời:


71

Bộ điều khiển như phiên bản (được khuyến nghị)

Đây là mẫu

<div ng-app="example" ng-controller="myController as $ctrl">
    <input type="text" ng-model="$ctrl.searchText" />
    <button ng-click="$ctrl.check()">Check!</button>
    {{ $ctrl.searchText }}
</div>

Mã thông báo

angular.module('example', [])
  .controller('myController', function() {
    var vm = this;
    vm.check = function () {
      console.log(vm.searchText);
    };
  });

Một ví dụ: http://codepen.io/Damax/pen/rjawoO

Tốt nhất sẽ là sử dụng thành phần với Angular 2.x hoặc Angular 1.5 trở lên

########

Cách (KHÔNG nên dùng)

Điều này KHÔNG được khuyến khích vì một chuỗi là nguyên thủy, rất được khuyến khích sử dụng một đối tượng thay thế

Hãy thử điều này trong đánh dấu của bạn

<input type="text" ng-model="searchText" />
<button ng-click="check(searchText)">Check!</button>
{{ searchText }}

và cái này trong bộ điều khiển của bạn

$scope.check = function (searchText) {
    console.log(searchText);
}

17
Điều này chỉ hoạt động một chiều ... nếu bạn muốn thay đổi giá trị của searchText?
cdmckay

199
Điều này cũng không trả lời "tại sao?" câu hỏi
cdmckay

4
Nếu tôi không muốn sử dụng bất kỳ nút nào thì sao? tôi cần gửi vào ví dụ
danikoren

2
Saniko => Để gửi khi nhập, bạn phải sử dụng thẻ biểu mẫu và ng-gửi trên đó ( docs.angularjs.org/api/ng.directive:ngSubmit )
Damax

1
@ HP's411 đó là vì một chuỗi là nguyên thủy. Khi Angular gán giá trị, nó thay đổi con trỏ thành giá trị, vì vậy bộ điều khiển nhìn vào giá trị cũ vì nó có con trỏ cũ thành giá trị.
Damax

620

"Nếu bạn sử dụng ng-model, bạn phải có một dấu chấm ở đó."
Làm cho mô hình của bạn trỏ đến một object.property và bạn sẽ ổn.

Bộ điều khiển

$scope.formData = {};
$scope.check = function () {
  console.log($scope.formData.searchText.$modelValue); //works
}

Bản mẫu

<input ng-model="formData.searchText"/>
<button ng-click="check()">Check!</button>

Điều này xảy ra khi phạm vi trẻ em đang chơi - như các tuyến đường con hoặc lặp lại ng. Phạm vi con tạo ra giá trị riêng của nó và xung đột tên được sinh ra như được minh họa tại đây :

Xem video clip này để biết thêm: https://www.youtube.com/watch?v=SBwoFkRjZvE&t=3m15s


94
Đây là câu trả lời thực sự.
keslert

16
@Catfish Với thừa kế nguyên mẫu, bất cứ khi nào bạn viết vào thuộc tính con, tham chiếu / kết nối đến thuộc tính cha mẹ sẽ không còn tồn tại. Cách mô hình Angular Scopes, nếu bạn không có dấu chấm, thì một thuộc tính mới trong phạm vi con của bạn được tạo. Video này giải thích chi tiết hơn: youtube.com/watch?v=ZhfUv0spHCY&feature=youtu.be&t=30m
Will Stern

1
Ông chủ Gracias. Đây là sự thật! Tuy nhiên, nó dường như không phải là một vấn đề nhất quán khi tôi gặp phải vấn đề chỉ khi sử dụng với khung Ionic
Don Barry

6
@ user3677331 Nó hoạt động tốt mà không có dấu chấm cho đến khi bạn có một phạm vi con cố gắng nói chuyện với nó (ví dụ như một mục trong vòng lặp ng). Giả sử tên mô hình của bạn là "điện thoại" Phạm vi con của bạn tạo ra "điện thoại", sau đó bạn gặp xung đột phạm vi vì phạm vi con có biến "điện thoại" và do đó không thể truy cập "điện thoại" trên phạm vi cha. Trong khi nếu phạm vi con tạo user.phone, nó sẽ được thêm vào đối tượng người dùng của cha mẹ để cả hai phạm vi đều trỏ đến cùng một đối tượng
Will Stern

3
Rất hữu ích. Tôi không chắc mình sẽ tìm được câu trả lời cho một câu hỏi tương đối mơ hồ nhưng điều này đã chết.
CodeManiak

57

Trong Làm chủ phát triển ứng dụng web với cuốn sách AngularJS trang 19, người ta viết rằng

Tránh các ràng buộc trực tiếp đến các thuộc tính của phạm vi. Liên kết dữ liệu hai chiều với các thuộc tính của đối tượng (được hiển thị trên một phạm vi) là một cách tiếp cận ưa thích. Theo nguyên tắc thông thường, bạn nên có một dấu chấm trong biểu thức được cung cấp cho chỉ thị ng-model (ví dụ: ng-model = "thing.name").

Phạm vi chỉ là các đối tượng JavaScript và chúng bắt chước hệ thống phân cấp dom. Theo Kế thừa nguyên mẫu JavaScript , các thuộc tính phạm vi được phân tách thông qua các phạm vi. Để tránh điều này, ký hiệu chấm nên sử dụng để liên kết các mô hình ng.


2
cảm ơn đã tham khảo Tôi coi đây là một điểm thú vị liên quan đến ng-model.
Các vị vua

44

Sử dụng thisthay vì $scopelàm việc.

function AppCtrl($scope){
  $scope.searchText = "";
  $scope.check = function () {
    console.log("You typed '" + this.searchText + "'"); // used 'this' instead of $scope
  }
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<div ng-app>
  <div ng-controller="AppCtrl">
    <input ng-model="searchText"/>
    <button ng-click="check()">Write console log</button>
  </div>
</div>

Chỉnh sửa: Tại thời điểm viết câu trả lời này, tôi đã có tình huống phức tạp hơn nhiều so với điều này. Sau khi nhận xét, tôi đã cố gắng tái tạo nó để hiểu tại sao nó hoạt động, nhưng không có may mắn. Tôi nghĩ bằng cách nào đó (không thực sự biết tại sao) một phạm vi con mới được tạo ra và thisđề cập đến phạm vi đó. Nhưng nếu $scopeđược sử dụng, nó thực sự đề cập đến phạm vi $ cha vì tính năng phạm vi từ vựng của javascript .

Sẽ thật tuyệt nếu ai đó gặp vấn đề này kiểm tra theo cách này và thông báo cho chúng tôi.


Hoàn hảo, bạn là một thiên tài
fjcero 24/07/2015

1
Có vẻ như các hàm được đính kèm để $scopetạo phạm vi mới (nghĩa là trong hàm check(), thisđề cập đến một phạm vi là phạm vi con $scope). Tại sao nó như vậy? Bạn có thể đưa ra một số lời giải thích?
Xun Yang

1
tại sao tôi nên sử dụng 'this' thay vì '$ scope' trong trường hợp này? bởi vì nó hoạt động bằng cách sử dụng $ scope trong dự án trước của tôi nhưng lần này điều tương tự không hoạt động khi sử dụng $ scope. Nhưng "cái này" đã hoạt động. Tại sao vậy?
Rashingul.Rubel

Điều này hoạt động, nhưng nếu bạn nói this.searchText = "something else"hoặc thậm chí nếu $scope.searchText = "something else", nó không cập nhật chế độ xem. bạn có thể giải thích vấn đề này?
Shri

nó nên Tôi đã thử nó bằng cách sử dụng mã ở trên, nó đã cập nhật khung nhìn.
Feyyaz

13

Tôi gặp vấn đề tương tự và đó là do tôi không khai báo đối tượng trống trước ở đầu bộ điều khiển của mình:

$scope.model = {}

<input ng-model="model.firstProperty">

Hy vọng điều này sẽ làm việc cho bạn!


10

Tôi đã gặp một vấn đề tương tự khi xử lý một quan điểm không tầm thường (có phạm vi lồng nhau). Và cuối cùng phát hiện ra đây là một điều khó khăn đã biết khi phát triển ứng dụng AngularJS do bản chất của sự kế thừa dựa trên nguyên mẫu của java-script. Phạm vi lồng nhau AngularJS được tạo ra thông qua cơ chế này. Và giá trị được tạo từ mô hình ng được đặt trong phạm vi con, không nói phạm vi cha mẹ (có thể là phạm vi được chèn vào bộ điều khiển) sẽ không thấy giá trị, giá trị cũng sẽ che phủ bất kỳ thuộc tính nào có cùng tên được xác định trong phạm vi cha nếu không sử dụng dấu chấm để thực thi một truy cập tham chiếu nguyên mẫu. Để biết thêm chi tiết, hãy xem video trực tuyến cụ thể để minh họa vấn đề này, http://egghead.io/video/angularjs-the-dot/ và bình luận theo dõi nó.


6

Hãy xem fiddle này http://jsfiddle.net/ganarajpr/MSjqL/

Tôi đã (tôi giả sử!) Đã làm chính xác những gì bạn đang làm và nó dường như đang hoạt động. Bạn có thể kiểm tra những gì không làm việc ở đây cho bạn?


Hmmmm .. cảm ơn vì đã xem xét điều này, tôi sẽ cho rằng nó sẽ hoạt động ... tại sao nó không hoạt động với tôi? Và điều quan trọng hơn: Tại sao nó hoạt động với các đối tượng và không có biến chuỗi đơn giản ?? Có lẽ vì tôi giới thiệu bộ điều khiển của mình theo cách không phù hợp trong routeProvider ?? Đã cố tránh toàn cầu và đã đặt bộ điều khiển của tôi dưới dạng modulename.ctrlName vào tệp controls.js. Điều đó có thể gây ra đau đầu?
giả kim

Tôi không thực sự chắc chắn tại sao nó không làm việc cho bạn. Nếu bạn có thể cô lập vấn đề này trong một câu đố, tôi đoán ai đó sẽ có thể cho bạn câu trả lời tốt hơn :)
ganaraj

Được rồi, sẽ làm, chỉ cần hoàn thành công việc bây giờ nhưng sẽ làm điều đó chắc chắn vào ngày mai hoặc muộn hơn vào buổi tối, chúc mừng! Có thể có một vấn đề với cách tôi đặt tên cho ctrl của mình, chúng ta sẽ thấy ...
giả kim

6

Vì không ai đề cập đến vấn đề này, vấn đề có thể được giải quyết bằng cách thêm $parentvào tài sản bị ràng buộc

<div ng-controller="LoginController">
    <input type="text" name="login" class="form-control" ng-model="$parent.ssn" ng-pattern="/\d{6,8}-\d{4}|\d{10,12}/" ng-required="true" />
    <button class="button-big" type="submit" ng-click="BankLogin()" ng-disabled="!bankidForm.login.$valid">Logga in</button>
</div>

Và bộ điều khiển

app.controller("LoginController", ['$scope', function ($scope) {
    $scope.ssn = '';

    $scope.BankLogin = function () {
        console.log($scope.ssn); // works!
    };
}]);

cảm ơn vì câu trả lời, tuy nhiên y có hoạt động không? lý tưởng nhất là nên làm việc trên cùng một yếu tố phạm vi chứ không phải cha mẹ?
V31

5

Đối với tôi, vấn đề đã được giải quyết bằng cách thả dữ liệu của tôi vào một đối tượng (ở đây là "dữ liệu").

NgApp.controller('MyController', function($scope) {

   $scope.my_title = ""; // This don't work in ng-click function called

   $scope.datas = {
      'my_title' : "",
   };

   $scope.doAction = function() {
         console.log($scope.my_title); // bad value
         console.log($scope.datas.my_title); // Good Value binded by'ng-model'
   }
   

});

Tôi hy vọng nó sẽ giúp


3
Ít chủ đề ở đây, nhưng 'dữ liệu' là một thuật ngữ số nhiều cho 'datum'
thethakuri

@thethakuri và "datum" trong tiếng Đức là "ngày", vì vậy tôi chắc chắn sẽ không sử dụng điều đó: P
EpicPandaForce

Tôi thích nhà bánh quế hơn IHOP
Nico Westerdale

2

Tôi chỉ gặp vấn đề này khi sử dụng root_controll liên kết với phần tử body. Sau đó, tôi đã sử dụng ng-view với bộ định tuyến góc. Vấn đề là LUÔN LUÔN tạo ra một phạm vi mới khi nó chèn html vào phần tử ng-view. Kết quả là, chức năng "kiểm tra" của tôi đã được xác định trên phạm vi chính của phạm vi được sửa đổi bởi phần tử ng-model của tôi.

Để giải quyết vấn đề, chỉ cần sử dụng bộ điều khiển chuyên dụng trong nội dung html được tải tuyến.


2

Bạn có thể làm điều đó để cho phép tìm kiếm ng-keypressnhập văn bản đầu vào và trong ng-clickbiểu tượng:

<input type="text" ng-model="searchText" ng-keypress="keyEnter(this,$event)" />
<button ng-click="check(searchText)">Check!</button>

in the controller
$scope.search = function (searchText) {
        console.log(searchText);
    }
    $scope.keyEnter = function (serachText,$event) {
        var keyCode = $event.which || $event.keyCode;
        if (keyCode === 13) {//KeyCode for Enter key
           console.log(searchText);
        }
    }

2

Tôi đã từng gặp vấn đề tương tự.
Cách thích hợp sẽ là đặt 'searchText' thành một thuộc tính bên trong một đối tượng.

Nhưng nếu tôi muốn để nó như vậy, một chuỗi thì sao? tốt, tôi đã thử mọi phương pháp duy nhất được đề cập ở đây, không có gì hiệu quả.
Nhưng sau đó tôi nhận thấy rằng vấn đề chỉ nằm ở sự khởi đầu, vì vậy tôi chỉ cần đặt thuộc tính giá trị và nó đã hoạt động.

<input type="text" ng-model="searchText" value={{searchText}} />

Bằng cách này, giá trị chỉ được đặt thành giá trị '$ scope.searchText' và nó được cập nhật khi giá trị đầu vào thay đổi.

Tôi biết đó là một cách giải quyết, nhưng nó đã làm việc cho tôi ..


2

Tôi đã phải đối mặt với cùng một vấn đề ... Độ phân giải phù hợp với tôi là sử dụng từ khóa này ..........

cảnh báo (this.ModelName);

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.