2013-06-02 10 views
10

Sto tentando di restituire un singolo record da una promessa in AngularJs (1.0.7) e associare il risultato a un modulo. Il modulo si collega correttamente, tuttavia i campi di input sono di sola lettura - Non riesco a modificare i valori.

Se invece avvolgo il record in un array e iterato utilizzando ng: repeat, il modulo si collega correttamente e posso modificare i valori.

ho creato un plnkr che dimostra chiaramente il problema:

http://embed.plnkr.co/fOWyhVUfekRbKUSRf7ut/preview

È possibile modificare l'elenco legato campi di input direttamente legati e, tuttavia il campo associato al singolo promessa non può essere modificato.

È possibile associare ng: model direttamente a un oggetto restituito da una promessa oppure è necessario utilizzare un array per farlo funzionare?

app.controller('MainCtrl', function($scope, $timeout, $q) { 

    var person = {"name": "Bill Gates"} 

    var deferList = $q.defer(); 
    var deferSingle = $q.defer(); 

    // Bind the person object directly to the scope. This is editable. 
    $scope.direct = person;  

    // Bind a promise to the scope that will return a list of people. This is editable. 
    $scope.list = deferList.promise; 

    // Bind ap romise to the scope that will return a single person record. This is *not* editable. 
    $scope.single = deferSingle.promise; 

    // Resolve the promises 
    $timeout(function(){ 
    deferList.resolve([person]); // Array 
    deferSingle.resolve(person); // Just the record itself 
    }, 100); 


}); 


<body ng-controller="MainCtrl"> 
    Directly Bound - This field is editable 
     <input ng:model="direct.name"/> 
    <hr/> 
    Singleton Promise - This field is *not* editable. 
     <input ng:model="single.name"/>  
    <hr/> 
    List Promise: - This field is editable 
     <div ng:repeat="person in list"> 
      <input ng:model="person.name"/> 
     </div> 

</body> 

Edit: Dopo un po 'di debug, ho trovato che il ng: direttiva modello è lettura dal valore ('$$ v'), componente della promessa, ma scrivendo direttamente alla promessa oggetto stesso.

Quando si tenta di modificare la promessa, ViewModel continua a ritornare al valore originale, mentre memorizza i caratteri sulla promessa stessa. Quindi se l'utente digita 'asdf' nel campo di input, il risultato sarebbe il seguente.

{Name: "Asdf", $$v: {Name: "Bill Gates"}} 

Mentre dovremmo invece aspettarci

{$$v: {Name: "asdf"}} 

Sto facendo qualcosa di sbagliato, o è questo potenzialmente un bug in AngularJS?

(Per chiarire ulteriormente, il problema è la differenza di comportamento tra un array e un oggetto restituito da una promessa. Il legame diretto è semplicemente lì come controllo)

+0

ho trovato il problema e hanno creato una richiesta di pull. https://github.com/angular/angular.js/pull/2854 –

risposta

8

UPDATE

Sembra che il problema è stato introdotto con AngularJS 1.0.3: http://jsfiddle.net/sonicsage/k8W4Y/6/

Se si passa a AngularJS 1.0.2, funzionerà.

C'è una questione aperta su GitHub: https://github.com/angular/angular.js/issues/1827

Il thread originale su Google Groups.

C'è anche un filo interessante scartare automatico qui: https://github.com/angular/angular.js/pull/1676


Con il debug dell'applicazione nella console Chrome, si può vedere che single è una funzione (la promessa):

> $('body.ng-scope').data('$scope').single 
Object {then: function, $$v: Object} 
$$v: Object 
then: function (b,g){var j=e(),h= 
__proto__: Object 

Mentre direct è un oggetto:

> $('body.ng-scope').data('$scope').direct 
Object {name: "Bill Gates", $$hashKey: "004"} 

Tuttavia, premendo i tasti sull'ingresso sola lettura ha un effetto sulla promise, per esempio, selezionando tutto il testo e cancellazione, anche se non ha effetto sull'interfaccia utente, ha un effetto sulla struttura:

è possibile eseguire il debug ulteriormente l'applicazione qui: http://run.plnkr.co/plunks/rDo7bFZlBq4rRH2ZNJn1/

EDIT

IMO direttamente vincolante la promessa di un campo non è supportato (è presente ufficialmente documentato?), modificando il codice come fol minime saranno lavorare:

// Bind ap romise to the scope that will return a single person record. This is *not* editable. 
    deferSingle.promise.then(function(data) { 
     $scope.single = data; 
    }, function(data) { 
     // error 
    }); 

Ecco il plunker: http://run.plnkr.co/plunks/rDo7bFZlBq4rRH2ZNJn1/

+0

oops, ho visto la tua modifica dopo aver postato la mia risposta. Non sono sicuro che si tratti di un bug di AngularJS. –

+0

Grazie. Non sono sicuro al 100% sul supporto che viene supportato, tuttavia funziona quasi in tutti i casi, e in parse.js c'è un codice specifico per gestire unwrapping $$ v. –

+0

Ovviamente il binding diretto funziona, tuttavia la cosa in particolare da notare è che la promessa che restituisce un 'Array' funziona, ma la promessa che restituisce un dizionario non lo è. Il legame diretto è stato semplicemente aggiunto come controllo. –