¿Cómo hacer que el enlace de tres vías funcione para objetos secundarios en AngularFire?
-
21-12-2019 - |
Pregunta
El siguiente código obtiene datos de Firebase y los vincula a $scope:
'use strict';
angular.module('costumeQueenApp')
.controller('ActorByUserIdActorIdCtrl', function ($scope,$routeParams,FireRef) {
var userId = $routeParams.user_id
var actorId = $routeParams.actor_id
var base = FireRef.actorById(userId, actorId)
$scope.base = base
$scope.base.$bind($scope, 'actor')
})
Y utiliza el siguiente código de plantilla para mostrar los datos (Nota:utiliza AngularUI-Bootstrap):
<accordion-group heading="Sizes">
<div ng-repeat="(key, value) in actor.sizes">
<label for="key">{{key}}</label> <input type="text" ng-model="value" />
</div>
</accordion-group>
El problema es que el enlace de datos de tres vías no funciona para los elementos dentro del div ng-repeat.Si tengo un campo de entrada que utiliza el campo completamente calificado en un campo de entrada, por ejemplo, actor.sizes.waist, todo funciona como se esperaba.
¿Cómo hago para que el enlace de datos funcione correctamente?
Solución
si reemplazas value
entonces básicamente has hecho: $childScope.value = somethingNew
.Como cualquier otra referencia de JavaScript, esta no modifica el contenido del objeto original.
Para decirlo de otra manera, establecer value
lo anterior es equivalente a esto:
var items = [{label: 'a'}, {label: 'b'}, {label: 'c'}];
angular.forEach(items, function(v, k) {
v = {foo: bar}; // does nothing to items! Only modifies the local variable `v`
});
Puedes solucionar este problema al usar angularFire usando $set
:
<accordion-group heading="Sizes">
<div ng-repeat="(key, value) in sizes">
<label for="key">{{key}}</label> <input type="text" ng-model="value" ng-change="actor.$child('sizes/'+key).$set(value)" />
</div>
</accordion-group>
Tenga en cuenta que ng-change
Parece un poco complicado aquí, pero investigar eso no pareció necesario para ilustrar la solución.
Además, si estás usando $bind
Para sincronizar datos, o si desea controlar el tiempo del evento de sincronización, puede simplemente configurar los datos en el objeto principal sin una llamada $set:
<accordion-group heading="Sizes">
<div ng-repeat="(key, value) in sizes">
<label for="key">{{key}}</label> <input type="text" ng-model="value" ng-change="actor.sizes[key] = value" />
</div>
</accordion-group>