Ng modeli denetleyici değerini güncellemiyor


270

Muhtemelen aptalca bir soru, ama basit giriş ve düğme ile benim html formu var:

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

Sonra denetleyicide (şablon ve denetleyici routeProvider'dan çağrılır):

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

Düğmeyi tıklattığınızda görünümün neden doğru şekilde güncellendiğini ancak konsolda tanımsız olduğunu görüyorum?

Teşekkürler!

Güncelleme: Ben aslında çözmüş gibi görünüyor bu mesele ile (bazı geçici çözümler ile gelip bulamadan): Yalnızca benim özellik adını değiştirmek zorunda searchTextiçin search.text, sonra boş tanımlamak $scope.search = {};hiçbir fikri denetleyici ve voila nesne ... Var neden 's çalışma rağmen ;]


Bu denetleyiciyi belgenin bu bölümünde kullandığınızdan emin misiniz? minimal başarısız bir örnek gönderebilir misiniz?
wroniasty

1
Evet,% 100 emin kontrolör o mesele ... bana tanıdık gibi görünüyor ben den özellik adı değiştirdiğinizde Şaşırtıcı çalıştığını, tamam searchTextiçin search.text, bir fikrin neden ??
simyalama

4
@Arthur: Bu çok açık değil ama ng-model, görüşünüzde yalnızca bir tür konuşma yerel değişkeni yaratıyor, bu şekilde tutmak istiyorsanız, check () işlevine geçirmeniz gerekir, örneğin: check ( searchText) ve denetleyiciniz bunu tanıyacaktır. Umut etmek bu yardım
simya 9

3
Kayıt için voiladeğil vuala, hecelendi wolla, vb.
Dan Bechard

3
Aradığınız cevabın stackoverflow.com/a/14049482/1217913
Willa

Yanıtlar:


71

Versiyon olarak kontrolör (önerilir)

İşte şablon

<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>

JS

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

Bir örnek: http://codepen.io/Damax/pen/rjawoO

En iyisi Açısal 2.x veya Açısal 1.5 veya üstü olan bileşen kullanmak olacaktır

########

Eski yol (önerilmez)

Bir dize ilkel olduğundan, bunun yerine bir nesne kullanılması şiddetle tavsiye edildiği için bu önerilmez

İşaretlemenizde bunu deneyin

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

ve bu kumandanızda

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

17
Bu sadece tek yönlü çalışır ... ya değerini değiştirmek isterseniz searchText?
cdmckay

199
Bu aynı zamanda "neden?" soru.
cdmckay

4
herhangi bir düğme kullanmak istemezsem ne olur? örneğin girmek için teslim etmek gerekiyor
danikoren

2
Saniko => Enter tuşuna basmak için form etiketini kullanmanız ve üzerinde ng-gönder yapmanız gerekir ( docs.angularjs.org/api/ng.directive:ngSubmit )
Damax

1
@ HP's411 bir dize ilkel olmasıdır. Açısal değeri atadığında, işaretçiyi değere değiştirir, böylece denetleyici eski değere bakar çünkü değere eski işaretçiye sahiptir.
Damax

620

"Ng-model kullanıyorsanız, orada bir nokta olması gerekir."
Modelinizi bir nesneye işaret edin. Mülk ve gitmekte fayda var.

kontrolör

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

şablon

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

Bu durum, alt kapsamlar oyunda olduğu gibi, alt yollar veya ng yinelemeleri gibi olduğunda olur. Alt kapsam kendi değerini oluşturur ve burada gösterildiği gibi bir ad çakışması ortaya çıkar :

Daha fazla bilgi için bu video klibe bakın: https://www.youtube.com/watch?v=SBwoFkRjZvE&t=3m15s


94
Gerçek cevap bu.
keslert

16
@Catfish Prototypal devralma ile, child özelliğine her yazışınızda, üst özelliğe başvuru / bağlantı kesilir. Açısal Kapsamlar modellerinin yolu, bir noktanız yoksa, alt kapsamınız dahilinde yeni bir özellik oluşturulur. Bu video daha ayrıntılı olarak açıklamaktadır: youtube.com/watch?v=ZhfUv0spHCY&feature=youtu.be&t=30m
Will Stern

1
Gracias Boss. Bu doğru! Ancak, sadece İyonik çerçeve ile kullanırken sorunla karşılaştığımda tutarlı bir tuhaf görünmüyor
Don Barry

6
@ user3677331 Konuşmaya çalışan bir alt kapsamınız olana kadar (örneğin, bir ng tekrarı içindeki bir öğe gibi) nokta olmadan iyi çalışır. Model adınızın "telefon" olduğunu varsayalım. Çocuk kapsamınız "telefon" oluşturur, çocuk kapsamının "telefon" değişkeni olduğu ve dolayısıyla ana kapsamdaki "telefon" a erişemediği için kapsam çakışması yaşarsınız. Alt kapsam user.phone oluşturuyorsa, her iki kapsam da aynı nesneyi işaret edecek şekilde ana öğenin kullanıcı nesnesine eklenir
Will Stern

3
Çok yararlı. Nispeten belirsiz bir sorunun cevabını bulacağımdan emin değildim ama bu durum bitmişti.
CodeManiak

57

AngularJS s.19 kitabı ile Web Uygulaması Geliştirme konusunda Ustalaşırken,

Kapsamın özelliklerine doğrudan bağlanmaktan kaçının. Nesnenin özelliklerine (bir kapsamda gösterilen) iki yönlü veri bağlama tercih edilen bir yaklaşımdır. Genel bir kural olarak, bir ifadede ng-model yönergesine (örneğin, ng-model = "thing.name") bir nokta konmalıdır.

Kapsamlar yalnızca JavaScript nesneleridir ve dom hiyerarşisini taklit ederler. Göre JavaScript Prototip Kalıtım , kapsamları özellikleri kapsamları ile ayrılır. Bundan kaçınmak için nokta modellerinin ciltleme modellerinde kullanılması gerekir.


2
bu referans için teşekkürler. Bunu ng modeli ile ilgili ilginç bir nokta olarak görüyorum.
Kings

44

İş thisyerine kullanmak $scope.

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>

Edit: Bu cevabı yazarken, bundan çok daha karmaşık bir durum vardı. Yorumlardan sonra, neden işe yaradığını anlamak için çoğaltmaya çalıştım, ama şans yok. Sanırım bir şekilde (neden bilmiyorum) yeni bir çocuk kapsamı oluşturuldu ve thisbu kapsamı ifade ediyor. Ancak $scopekullanılırsa, javascript'in sözcüksel kapsam özelliği nedeniyle aslında ana $ kapsamını ifade eder .

Bu sorunu yaşayan biri bu şekilde test edip bizi bilgilendirirse harika olur.


Kusursuz, sen bir dahisin
fjcero

1
Ekli işlevler $scopeyeni bir kapsam oluşturur gibi görünür (yani işlevde check(), thisalt kapsamı olan bir kapsamı ifade eder $scope). Neden böyle? Bazı açıklamalar yapabilir misiniz?
Xun Yang

1
neden bu durumda '$ scope' yerine 'this' kullanmalıyım? çünkü önceki projemde $ scope kullanarak çalıştı ancak bu sefer $ scope kullanılarak aynı şey çalışmaz. Ama 'bu' işe yaradı. Neden?
Rashedul.Rubel

Bu işe yarıyor, ancak siz söyleseniz this.searchText = "something else"veya söyleseniz bile $scope.searchText = "something else"görünümü güncellemiyor. bu sorunu açıklayabilir misin?
Shri

olması gerekiyor. Yukarıdaki kodu kullanarak denedim, görünümü güncelledi.
Feyyaz

13

Ben de aynı sorunu vardı ve benim denetleyicisi üstündeki boş nesneyi ilk ilan değil bana oldu:

$scope.model = {}

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

Umarım bu sizin için çalışır!


10

Önemsiz bir görünümle uğraşırken aynı sorunla karşılaştım (iç içe kapsamlar var). Ve nihayet bu java-script prototip tabanlı kalıtım doğası nedeniyle AngularJS uygulama geliştirirken bilinen bir zor şey olduğunu keşfetti. Bu mekanizma ile AngularJS iç içe kapsamları oluşturulur. Ve ng-modelinden yaratılan değer, ana kapsamın (belki de denetleyiciye enjekte edilen) değeri görmeyeceğini söyleyerek çocuk kapsamına yerleştirilir, değer ayrıca nokta kullanılmazsa üst kapsamda tanımlanan aynı ada sahip herhangi bir özelliği gölgeleyecektir bir prototip başvuru erişimini zorlamak için. Daha fazla ayrıntı için, http://egghead.io/video/angularjs-the-dot/ ve bu konuyu izleyen yorumlar için özel çevrimiçi videoyu inceleyin .


6

Bu kemana bir göz atın http://jsfiddle.net/ganarajpr/MSjqL/

Yaptığınızı tam olarak yaptım (sanırım!) Ve çalışıyor gibi görünüyor. Burada sizin için neyin işe yaramadığını kontrol edebilir misiniz?


Hmmmm .. Buna baktığın için teşekkürler, işe yaraması gerektiğini varsayacağım ... neden benim için çalışmıyor? Ve daha da önemlisi: Neden nesnelerle çalışıyor ve düz dize değişkenleriyle çalışmıyor ?? Belki de kontrolörlerime routeProvider'da uygun olmayan bir şekilde atıfta bulunuyorum. Globals önlemek ve denetleyicilerimi modulename.ctrlName olarak controllers.js dosyasına koymaya çalışıyordu. Bu baş ağrısına neden olabilir mi?
simyalama

Neden senin için işe yaramadığından emin değilim. Bu sorunu bir
kemanda

Tamam, şimdi çalışmayı bitireceğim, ama yarın ya da akşam saatlerinde emin olacağım, şerefe! Ctrl'lerimi adlandırma yöntemimle ilgili bir sorun olabilir, göreceğiz ...
simyalaştırma

6

Hiç kimse bundan bahsetmediği için problem $parentbound özelliğine eklenerek çözülebilir

<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>

Ve kontrolör

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

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

cevap için teşekkürler, ancak bu çalışıyor mu? ideal olarak ebeveyn için değil aynı kapsam öğesi üzerinde mi çalışmalıdır?
V31

5

Benim için sorun, verilerimi bir nesneye (burada "veriler") stoklayarak çözüldü.

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'
   }
   

});

Umarım yardımcı olur


3
Burada çok az konu var, ancak 'veri' 'datum' için çoğul bir terim
thethakuri

Macarca @thethakuri ve "datum" "tarih" olduğunu, bu yüzden ben de bunu kullanmazsınız: P
EpicPandaForce

Gözleme evini
IHOP'a

2

Ben sadece vücut elemanına bağlı bir root_controller kullanarak bu sorunu vardı. Sonra açısal yönlendirici ile ng-view kullanıyordum. Sorun, açısal DAİMA html'yi ng-view öğesine eklediğinde yeni bir kapsam oluşturmasıdır. Sonuç olarak, "kontrol" fonksiyonum, ng-model elemanım tarafından değiştirilen kapsamın ana kapsamı üzerinde tanımlanmıştır.

Sorunu çözmek için, rota yüklü html içeriğinde özel bir denetleyici kullanın.


2

Bunu, ng-keypressgiriş metni için giriş ve ng-clicksimge için giriş özelliğini etkinleştirmek için yapabilirsiniz :

<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

Ben de aynı problemi yaşadım.
Doğru yol, 'searchText'i bir nesnenin içindeki bir özellik olacak şekilde ayarlamak olacaktır.

Ama ya olduğu gibi bırakmak istersem, bir dize? burada bahsettiğim her yöntemi denedim, hiçbir şey işe yaramadı.
Ama sonra sorunun sadece inisiyasyonda olduğunu fark ettim, bu yüzden sadece değer niteliğini ayarladım ve işe yaradı.

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

Bu şekilde değer sadece '$ scope.searchText' değerine ayarlanır ve girdi değeri değiştiğinde güncellenir.

Bunun bir çözüm olduğunu biliyorum, ama benim için çalıştı.


2

Aynı sorunla karşı karşıya kaldım ... Benim için çalışan çözüm bu anahtar kelimeyi kullanmaktır ..........

uyarısı (this.ModelName);

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.