javascript - cloak - ng-if
AngularJS: $ scope. $ Watch no está actualizando el valor obtenido de $ resource en una directiva personalizada (4)
¿No puedo ver que está utilizando el controlador SeatsCtrl
cualquier lugar? ¿Cómo se está utilizando? ¿Y ha verificado que está activado y que la consulta se realiza realmente?
La forma más rápida de verificar si SeatsCtrl está en uso es simplemente agregar una console.log(''SeatsCtrl actived!'');
dentro de eso. Si no lo está, a continuación, agregue ng-controller="SeatsCtrl"
a la div
.
También puede colocar un reloj y un registro en los asientos directamente dentro del controlador para asegurarse de que no sea un problema con el alcance.
Tengo un problema con las directivas personalizadas que me están volviendo loco. Estoy tratando de crear la siguiente directiva personalizada (atributo):
angular.module(''componentes'', [])
.directive("seatMap", function (){
return {
restrict: ''A'',
link: function(scope, element, attrs, controller){
function updateSeatInfo(scope, element){
var txt = "";
for (var i in scope.seats)
txt = txt + scope.seats[i].id + " ";
$(element).text("seat ids: "+txt);
}
/*
// This is working, but it''s kind of dirty...
$timeout(function(){updateSeatInfo(scope,element);}, 1000);
*/
scope.$watch(''seats'', function(newval, oldval){
console.log(newval, oldval);
updateSeatInfo(scope,element);
});
}
}
});
Esta directiva de "tipo de atributo" (llamada mapa de asiento) está tratando de mostrar una lista de identificadores de asiento (por ejemplo, para un teatro) que obtendré del servidor a través del servicio $ resource (vea el código a continuación) en un div (elemento) .
Lo estoy usando con este simple html parcial:
<div>
<!-- This is actually working -->
<ul>
<li ng-repeat="seat in seats">{{seat.id}}</li>
</ul>
<!-- This is not... -->
<div style="border: 1px dotted black" seat-map></div>
</div>
Y este es el controlador que está cargando el alcance:
function SeatsCtrl($scope, Seats) {
$scope.sessionId = "12345";
$scope.zoneId = "A";
$scope.seats = Seats.query({sessionId: $scope.sessionId, zoneId: $scope.zoneId});
$scope.max_seats = 4;
}
Donde "Seats" es un servicio simple que usa $ resources para obtener un JSON del servidor
angular.module(''myApp.services'', [''ngResource''])
.factory(''Seats'', function($resource){
return $resource(''json/seats-:sessionId-:zoneId.json'', {}, {});
})
;
app.js (asientos_libres.html es el parcial que he estado usando):
angular.module(''myApp'', [''myApp.filters'', ''myApp.services'', ''myApp.directives'', ''componentes'']).
config([''$routeProvider'', function($routeProvider) {
$routeProvider.when(''/view1'', {templateUrl: ''partials/asientos_libres.html'', controller: SeatsCtrl});
$routeProvider.otherwise({redirectTo: ''/view1''});
}]);
El problema es que, aunque configuré un "scope. $ Watch" en la función de enlace de la directiva para que el alcance pueda verificar si el atributo de "asientos" ha cambiado para actualizar la lista de identificadores, no está funcionando en el El momento en que $ scope.seats está cambiando en el controlador (cuando llamamos "consulta").
Como puede ver en el código, intenté usar $ timeout para retrasar el lanzamiento de "updateSeatInfo", pero me temo que no es la solución más inteligente por mucho ...
También traté de no hacer una solicitud JSON, pero uso un diccionario codificado en $ scope.seats y funciona, así que parece que es una cuestión de sincronía.
Nota: updateSeatInfo es solo una función de prueba, la función real que usaré es un poco más compleja.
¿Alguna idea de cómo lidiar con eso?
Muchas gracias de antemano!
Edición 1: Se agregó app.js, donde estoy usando un enrutador para llamar a SeatsCtrl, gracias a Supr por el consejo. Sin embargo, todavía tengo el mismo problema.
Edición 2: ¡Resuelto! (?) ¡Ok! Parece que encontré una solución, que puede no ser la mejor, ¡pero está funcionando correctamente! :) Por lo que pude ver aquí http://docs.angularjs.org/api/ng.$timeout , podemos usar $ timeout (una envoltura sobre setTimeout) sin demora . Esto es genial porque no estamos retrasando artificialmente la ejecución de nuestro código dentro de $ timeout, pero estamos haciendo la directiva de no ejecutarlo hasta que la solicitud asíncrona haya finalizado.
Espero que funcione para solicitudes de larga espera, también ...
Si alguien sabe una mejor manera de arreglarlo, por favor dígaselo!
El problema es que el reloj compara la referencia en lugar del objeto por defecto. Agregue, hasta el final para que compare el valor en su lugar.
scope.$watch(''seats'', function(newval, oldval){
console.log(newval, oldval);
updateSeatInfo(scope,element);
}, true);
Tengo este problema también. Creo que es un problema en Angular. Hay un boleto en GitHub para "reforzar $ futuros de recursos" que probablemente abordará este problema, ya que lo que realmente necesita es acceso al objeto de promesa para el recurso que tiene.
O bien, los observadores podrían esperar a disparar hasta que se resuelva la promesa.
Mientras tanto, una forma un poco más elegante de solucionar este problema que no requiere un tiempo de espera es reasignar la propiedad de alcance que se está observando desde la devolución de llamada correcta en el recurso $. Esto hará que el observador vuelva a disparar en el momento adecuado.
Un tiempo de espera sin demora es simplemente poner la evaluación de la función diferida al final de la pila actual; en su caso, su recurso se resolvió para entonces, pero esto podría ser un problema si el servidor tiene un caso de Los lunes
Ejemplo:
$scope.myAttr = MyResource.fetch(
function (resource) { $scope.myAttr = new MyResource(angular.copy(resource)); }
);
Yo tuve este problema también. Fue debido al hecho de que mi variable al principio no estaba definida como "indefinida" en el alcance. El reloj parece no funcionar en variables indefinidas. Parece obvio después de todo.
Primero estaba tratando de usar el reloj para disparar cuando mi variable sería efectivamente establecida por el controlador. Ejemplo:
myApp.controller(''Tree'', function($scope, Tree) {
Tree.get({},
function(data) { // SUCCESS
console.log("call api Tree.get succeed");
$scope.treeData = data;
},
function(data) { // FAILURE
console.log("call api Tree.get failed");
$scope.treeData = {};
});
});
Lo resolví inicializando mi variable con un objeto vacío antes de llamar al servicio:
myApp.controller(''Tree'', function($scope, Tree) {
$scope.treeData = {}; // HERE
Tree.get({},
function(data) { // SUCCESS
console.log("call api Tree.get succeed");
$scope.treeData = data;
},
function(data) { // FAILURE
console.log("call api Tree.get failed");
$scope.treeData = {};
});
});
En ese caso, Watch pudo detectar el cambio en la variable.