ngmodelchange event change javascript angularjs angularjs-ng-repeat

javascript - event - ng model change angularjs



AngularJS no refresca ngRepetir cuando actualiza la matriz (3)

Tengo problemas serios para entender AngularJS algunas veces. Así que tengo una matriz básica en mi controlador como

$scope.items = ["a","b","c"]

Estoy ngRepeating en mi plantilla sobre la matriz de elementos ng-repeat = "elemento en elementos". Super straightfoward hasta el momento. Después de un par de acciones de UX, quiero enviar algunas cosas nuevas a mi matriz.

$scope.items.push("something");

Entonces, el 50% del tiempo, el nuevo elemento se agrega a la vista. Pero el otro 50%, nada sucede. Y es como super frustrante; bc si lo envuelvo dentro de $ scope. $ apply (), recibí el error "$ digest ya in progress". Envolver eso en $ timeout no ayuda tampoco.

Y cuando inspecciono el alcance de mi elemento usando la extensión Chrome; Puedo ver que los nuevos datos están allí y que el valor $ scope.items es correcto. Pero la vista simplemente no se ocupa de agregar eso al DOM.

¡Gracias!


Como señaló Umur Kontacı, a veces se están haciendo cambios de modelo fuera del ciclo de resumen. Sin embargo, en lugar de solucionar este problema y tratar de detectar si se encuentra en un contexto de aplicación / resumen, le sugiero que se asegure de que esto nunca suceda.

La causa principal de este problema es que su función se llama como una reacción a un evento DOM. P.ej

jQuery(''.some-element'').click(function() { seeminglyProblematicCode() })

Aquí es donde debe aplicar $ apply (), no dentro de la función. De lo contrario, todo su código estará lleno de tales distinciones tarde o temprano. Suponiendo que hay un alcance en el contexto de este controlador de eventos, puede escribir:

jQuery(''.some-element'').click(function() { $scope.$apply(function() { seeminglyProblematicCode() }) })

Sin embargo, hay que tener en cuenta una advertencia: cuando active un evento de clic desde su código, se encontrará con el problema de que un ciclo de resumen ya está en curso. Aquí es donde necesitas el $ timeout. Las respuestas a esta pregunta cubren muy bien este problema.


Está modificando el alcance fuera del ciclo de $digest de angular el 50% del tiempo.

Si hay una devolución de llamada que no es de angularjs; (posibbly jquery). Necesitas llamar a $apply para forzar un ciclo de $digest . Pero no puede llamar a $apply mientras esté en el ciclo de $digest porque cada cambio que realice se reflejará automáticamente ya.

Necesita saber cuándo la devolución de llamada no es de angular y debe llamar $apply solo en ese momento.

Si no sabes y no puedes aprender, he aquí un buen truco:

var applyFn = function () { $scope.someProp = "123"; }; if ($scope.$$phase) { // most of the time it is "$digest" applyFn(); } else { $scope.$apply(applyFn); }


Tuve el mismo problema, y ​​mi solución fue ver qué controladores se están llamando en directivas anidadas.

# Parent Controller app.controller ''storeController'', ($scope, products) -> $scope.cart = ["chicken", "pizza"] $scope.addToCart = (item) -> $scope.cart.push item # from service products.get().then (items) -> $scope.products = items # Parent Directives app.directive ''storeContainer'', ($scope, config) -> restrict: ''E'' templatUrl: ''store-container.html'' controller: ''storeController'' # Nested Directive app.directive ''storeFront'', ($scope, config) -> restrict: ''E'' templatUrl: ''store-front.html'' controller: ''storeController'' # Parent Template templates/directives/store-container.html <div ng-repeat="item in cart">{{ item }}</div> <strore-front></store-front> # Nested Template templates/directives/store-front.html <ul ng-repeat="item in products"> <li ng-click"addToCart(item)">{{ item }}</li> </ul>

El error aquí es que la directiva anidada crea un segundo controlador en la cadena de prototipos (un duplicado de storeController), al que la plantilla principal no tiene acceso. Para resolver, escriba el controlador anidado de la siguiente manera:

# Nested Directive app.directive ''storeFront'', ($scope, config) -> restrict: ''E'' templatUrl: ''store-front.html''

Hay mejores formas de crear la cadena de herencia, pero esto resolverá el problema para muchas personas que aprenden AngularJS.