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.