2015-12-26 1 views
0

J'ai créé une structure de directive imbriquée avec liaison de données d'objet bidirectionnel. Tout a fonctionné comme un charme sur le côté js, jusqu'à ce que je l'ai connecté à mes services qui envoient les données à mon API. Parce que dans la demande de publication, l'objet a des valeurs anciennes, il ignore toujours la dernière modification. Mais le vrai problème est ... sortie de l'objet juste avant que je le passe à la demande, il a les bonnes valeurs mises à jour.

service.updatePerson = function(person) { 
     console.log(person); //this outputs the correct up to date data 
     $http.post(Routing.generate('update_person'), person); // this works not 

     //After trying some more (see update below) - this works as well 
     $timeout(function() { 
      $http.post(Routing.generate('update_person'), person); 
     }, 1000); 
}; 

(je me sers du paquet de routage fos pour symfony)

la demande avec Inspecter mes outils de développement, je peux voir que l'objet soumis a des valeurs anciennes. Mais ce n'est pas comme si les valeurs ne changeaient jamais, c'est toujours le dernier mais pas le changement actuel.

Je suis tout à fait nouveau à angulaire et pourrait oublier quelque chose de spécial sur le service $ http - je n'ai pas activé le cache, ce qui ne devrait pas être le problème. Aussi le problème se produit uniquement avec les objets mis à jour, pas si j'envoie une nouvelle entité complète.

La seule différence que je peux voir et je soupçonne de causer le problème est la profondeur de l'imbrication. J'ai une directive appelée 'collapsedTable' qui prend différentes données. Non seulement les données, mais aussi la méthode update, add et delete sont passées à la directive.

C'est l'utilisation de la directive:

<collapsed-table ng-if="formModel" ng-if="persons" view-data="persons" form-model="formModel" add-object="newPerson" add-item="addPerson(item)" update-item="updatePerson(item)" delete-item="deletePerson(item)"></collapsed-table> 

Ajout et suppression d'éléments qui se passe directement dans la directive:

<button href="#" class="btn btn-success pull-right" ng-click="addItem({item : newItem})"> 
      Add 
</button> 

(bouton de suppression semble le même, mais appelle la fonction de suppression)

Mais la mise à jour des données ne se fait pas via un bouton, elle est liée directement aux champs de formulaire et les champs de formulaire sont sa propre directive:

<form-field ng-if="column.type" form-field-bind="item[column.name]" form-field-action="updateItem({item:item})" form-field-action-param="item" form-select-options="column.data" form-template="{{column.type}}"></form-field> 

(je sais, merde générique qui se passe ici)

et dans la directive (editableTextarea pour un exemple):

<a href="#" onaftersave="formFieldAction({item : formFieldActionParam})" editable-textarea="$parent.formFieldBind">{{formFieldBind || 'eintragen'}}</a> 

(en utilisant le module x modifiable pour ici angulaire)

Je pense que l'affichage de tout le contenu de mes directives va trop loin. Mais je pense que les paramètres de la portée sont pertinents pour unterstand comment les fonctions et les variables sont transmises.

collapsedTableDirective.js

.directive('collapsedTable',['$filter',function($filter) { 
    return { 
     restrict: 'E', 
     templateUrl: 'templates/collapsedTableView.html', 
     scope: { 
      data: "=viewData", 
      newItem: '=addObject', 
      formModel: '=', 
      deleteItem: '&', 
      updateItem: '&', 
      addItem: '&' 
     } 
    } 
}]); 

formFieldDirective.js

.directive('formField',['formTemplateFactory', '$filter',function(formTemplateFactory, $filter) { 
    return { 
     restrict: 'E', 
     scope: { 
      formFieldBind: '=', 
      formFieldActionParam: '=', 
      formFieldAction: '&', 
      formTemplate: '@', 
      formSelectOptions: '=' 
     }, 
     transclude: true, 
     template: '<div ng-include="getTemplate()"></div>' 
    } 
}]); 

je montre aussi que les modèles de champ de formulaire sont tirés par ng comprennent, ce qui crée une nouvelle portée et qui est la raison pourquoi la variable liée est référencée avec "parent" dans le modèle de champ de formulaire.

Mais avec toutes les questions qui peuvent être éventuellement abordés ici, ne pas oublier:

console.log délivre les données correctes au sein du service. Seulement à l'intérieur de la demande, nous avons d'anciennes données. C'est aussi une raison assez difficile à déboguer ... Du côté du débogueur, mes objets ont toujours l'air bien.

Toute aide appréciée!

MISE À JOUR - avec délai de $ il fonctionne

Après avoir essayé quelques trucs, j'ai eu l'idée d'essayer un timeout (à partir d'un poste sans aucun rapport). Et oui, un timeout fait l'affaire. Mais je ne réponds pas à la question parce que je n'ai pas vraiment d'explication pour ce comportement. Le console.log n'a pas besoin d'un tiemout, bien qu'il devrait être exécuté avant la demande de publication. Il existe également probablement une solution plus appropriée que l'utilisation d'un délai d'expiration.

Répondre

0

person n'est pas mis à jour au moment où service.updatePerson s'exécute, et il semble qu'il est déclenché par un code non-angulaire qui n'est pas adapté pour digérer les cycles. Dans ce cas, ce

$scope.$apply(); 
    // or $rootScope.$apply() if this is a service and not a controller 
    $http.post(Routing.generate('update_person'), person); 

peut aider, mais faire $apply en fonction de l'appelant et non callee est toujours une meilleure habitude, donc JS externe doit déclencher une enveloppe à la place:

scope.externalAction = function (obj) { 
    scope.$apply(function() { 
    scope.formFieldAction(obj); 
    }; 
}; 

console.log ne délivre pas les données qui étaient réelles à ce moment-là car elles étaient fournies avec la référence d'objet, et elles peuvent refléter les changements qui ont eu lieu après l'appel de console.log. C'est une fonctionnalité utile si elle est prise en compte, sinon c'est nocif.

Pour enregistrer l'état actuel de l'objet toujours utiliser

console.log(JSON.stringify(person)); 
+0

Salut ESTUS :-) Merci pour votre réponse et merci sur la pointe comment connecter les objets! Cela semble être le problème ... J'utilise le module xeditable, qui est un module angulaire et la méthode de mise à jour n'est pas appelée via un événement angulaire mais un événement de cette directive. La seule chose qui me dérange ici, c'est que ce problème ne s'est pas produit avant que j'ajoute une autre couche avec la nouvelle directive, je devine juste que le module n'applique pas correctement les changements avec ses événements personnalisés si une couche d'une portée isolée est ajoutée. – SamiSalami