Ng-model no actualiza el valor del controlador


Probablemente una pregunta tonta, pero tengo mi formulario html con entrada simple y botón:

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

Luego en el controlador (la plantilla y el controlador se llaman desde routeProvider):

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

¿Por qué veo la vista actualizada correctamente pero indefinida en la consola al hacer clic en el botón?

Gracias!

Actualizar: Parece que en realidad he resuelto ese problema (antes tenía que llegar a algunas soluciones) con: Solo tuve que cambiar el nombre de mi propiedad de searchText a search.text, entonces defina un objeto $scope.search = {}; vacío en el controlador y listo... Sin embargo, no tengo idea de por qué está funcionando;]

Author: Damjan Pavlica, 2012-09-27

13 answers

Controlador como versión (recomendado)

Aquí la plantilla

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

La JS

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

Un ejemplo: http://codepen.io/Damax/pen/rjawoO

Lo mejor será usar componente con Angular 2.x o angular 1.5 o superior

########

Antiguo camino (NO recomendado)

Esto NO se recomienda porque una cadena es una primitiva, muy recomendable usar un objeto en su lugar

Pruebe esto en su marcado

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

Y esto en su controlador

$scope.check = function (searchText) {
    console.log(searchText);
}
 64
Author: Damax,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-05 09:17:54

"Si usas ng-model, tienes que tener un punto ahí."
Haga que su modelo apunte a un objeto.propiedad y usted será bueno para ir.

Controlador

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

Plantilla

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

Esto sucede cuando los ámbitos secundarios están en juego, como rutas secundarias o repeticiones ng. El child-scope crea su propio valor y nace un conflicto de nombres como se ilustra aquí:

Vea este video clip para más información: https://www.youtube.com/watch?v=SBwoFkRjZvE&t=3m15s

 579
Author: Will Stern,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-06-30 19:57:36

En el Dominio del Desarrollo de Aplicaciones Web con AngularJS libro p. 19, está escrito que

Evite los enlaces directos a las propiedades del ámbito. Enlace de datos bidireccional a las propiedades del objeto (expuestas en un ámbito) es un enfoque preferido. Como regla general, debe tener un punto en una expresión proporcionada a la directiva ng-model (por ejemplo, ng-model="thing.name").

Los ámbitos son solo objetos JavaScript, e imitan la jerarquía dom. De acuerdo con JavaScript Prototype Inheritance , las propiedades de scopes se separan a través de scopes. Para evitar esto, la notación de puntos debe usarse para enlazar modelos ng.

 55
Author: efirat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-11-20 15:23:27

Usando this en lugar de $scope funciona.

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: En el momento de escribir esta respuesta, tenía una situación mucho más complicada que esta. Después de los comentarios, traté de reproducirlo para entender por qué funciona, pero no hubo suerte. Creo que de alguna manera (realmente no sé por qué) se genera un nuevo ámbito hijo y this se refiere a ese ámbito. Pero si se usa $scope, en realidad se refiere al ámbito padre because debido al ámbito léxico de javascript función.

Sería genial si alguien que tiene este problema prueba de esta manera y nos informa.

 39
Author: Feyyaz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:02:49

Tuve el mismo problema y se debió a que no declaré el objeto en blanco primero en la parte superior de mi controlador:

$scope.model = {}

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

¡Espero que esto funcione para ti!

 10
Author: Millsionaire,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-15 11:59:23

Me encontré con el mismo problema cuando se trata de una vista no trivial (hay ámbitos anidados). Y finalmente descubrió que esto es una cosa difícil conocida al desarrollar la aplicación AngularJS debido a la naturaleza de la herencia basada en prototipos de java-script. Los alcances anidados AngularJS se crean a través de este mecanismo. Y el valor creado a partir de ng-model se coloca en el ámbito secundario, sin decir que el ámbito primario (tal vez el que se inyecta en el controlador) no verá el valor, el valor también sombreará cualquier propiedad con el mismo nombre definida en el ámbito principal si no se usa dot para imponer un acceso de referencia de prototipo. Para obtener más detalles, consulte el video en línea específico para ilustrar este problema, http://egghead.io/video/angularjs-the-dot / y comentarios posteriores.

 9
Author: Roger Jin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-04-03 02:04:22

Echa un vistazo a este violín http://jsfiddle.net/ganarajpr/MSjqL /

Tengo ( supongo! ) hecho exactamente lo que estaba haciendo y parece estar funcionando. ¿Puedes comprobar lo que no funciona aquí para ti?

 5
Author: ganaraj,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-09-27 11:12:39

Para mí el problema se resolvió almacenando mis datos en un objeto (aquí "datos").

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

});

Espero que ayude

 4
Author: Plici Stéphane,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-21 15:24:18

Dado que nadie mencionó esto, el problema se puede resolver agregando $parent a la propiedad enlazada

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

Y el controlador

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

    $scope.BankLogin = function () {
        console.log($scope.ssn); // works!
    };
}]);
 3
Author: Eric Herlitz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-18 13:22:15

Acabo de tener este mismo problema usando un root_controller enlazado al elemento body. Luego estaba usando ng-view con el router angular. El problema es que angular SIEMPRE crea un nuevo ámbito cuando inserta el html en el elemento ng-view. Como consecuencia, mi función" check " se definió en el ámbito padre del ámbito que fue modificado por mi elemento ng-model.

Para resolver el problema, simplemente use un controlador dedicado dentro del contenido html cargado por ruta.

 1
Author: moritz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-03-13 07:12:42

Puede hacer eso para habilitar la búsqueda en ng-keypress enter para el texto de entrada y en ng-click para el icono:

<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);
        }
    }
 1
Author: Naoufal Gaffa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-09-04 09:50:06

Yo tenía el mismo problema.
La forma correcta sería configurar el 'SearchText' para que sea una propiedad dentro de un objeto.

Pero ¿qué pasa si quiero dejarlo como está, una cadena? bueno, probé todos los métodos mencionados aquí, nada funcionó.
Pero luego me di cuenta de que el problema es sólo en la iniciación, así que he establecido el atributo de valor y funcionó.

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

De esta manera el valor se establece en 'scope scope.Valor de SearchText y se actualiza cuando el valor de entrada cambio.

Sé que es una solución alternativa, pero funcionó para mí..

 1
Author: Hike Nalbandyan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-15 13:31:41

Me enfrentaba al mismo problema... La resolución que funcionó para mí es usar esta palabra clave..........

Alerta(esto.ModelName);

 1
Author: SnktJavaMaster,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-30 08:57:51