2015-10-15 19 views
8

Dare il codice all'interno del mio controllo:Uso delle espressioni in ngModel in Angular.js

$scope.entity = { 
    firstName: 'Jack', 
    lastName: 'Bauer', 
    location: { 
    city: 'New York' 
    } 
}; 
$scope.path = 'location.city'; 

Come faccio a legarsi in modo dinamico ngModel alla proprietà del entity specificato da path?

Ho provato qualcosa di simile, ma senza alcun risultato:

<input ng-model="'entity.' + path"> 

risposta

7

Slava, non sono sicuro se sia una buona idea per cominciare. Ma comunque, È necessario rendere il modello getterSetter consapevole aggiungendo questa proprietà al proprio input ng-model-options="{ getterSetter: true }. Quindi è necessaria una funzione nel controller che costruisca un getterSetter da una puntura.

<input type="text" ng-model="propertify('entity.' + path)" ng-model-options="{ getterSetter: true }"> 

Ecco come apparirà il modello risultante.

Fortunatamente angolare ha un servizio $ parse che lo rende molto più semplice. quindi qualcosa del genere dovrebbe essere nel controller, o anche meglio in un servizio iniettato.

$scope.propertify = function (string) { 
     var p = $parse(string); 
     var s = p.assign; 
     return function(newVal) { 
      if (newVal) { 
       s($scope,newVal); 
      } 
      return p($scope); 
     } ; 
    }; 

Ciò restituirà una funzione getter-setter che gestisce ciò per voi. vederlo in azione in this plunk

+0

Sander, sei un angoloso-ninja per davvero, grazie mille! =) –

+0

Sto ancora ottenendo l'errore "non assegnabile" con questo ... ma il tuo plunkr funziona perfettamente – ProblemsOfSumit

+0

Ho avuto la versione angolare sbagliata - funziona tutto alla grande, grazie! – ProblemsOfSumit

2

Si potrebbe usare la notazione staffa con una piccola modifica, come si desidera associare a una proprietà nidificato. È necessario dividere il percorso alla proprietà:

<input ng-model="entity[locationKey][cityKey]"/> 

Controller:

$scope.locationKey = 'location'; 
$scope.cityKey = 'city'; 

Vedi js fiddle

+0

Grazie, ma non lo farà, io memorizzare il percorso completo in una singola variabile, che è il cuore del problema. –

7

Aggiornamento

E 'che non funziona come previsto, il valore è visualizzato correttamente, ma non può essere modificato. La soluzione corretta è fornita da Sander here.


soluzione non corretta

Wow, risolto accidentalmente:

<input type="text" ng-model="$eval('entity.' + path)"> 

Ed ecco il Plunk.

Spero che possa aiutare qualcuno.

1

Dopo aver letto e utilizzato la risposta di Sander Elias, stavo usando questo, ma ho incontrato un altro problema.

Quando si combina il suo risultato con ng-required="true" nel <input> non si poteva svuotare il campo, perché quando il campo sarebbe vuoto, il newVal viene passato come undefined.

Dopo ulteriori ricerche, ho trovato an isssue on GitHub che risolve e risolve questo problema.

Ecco cosa Sander e l'aspetto GitHub risposta combinata come:

$scope.propertify = function (string) { 
    var property = $parse(string); 
    var propAssign = property.assign; 
    return function (newVal) { 
     if (arguments.length) { 
      newVal = angular.isDefined(newVal)? newVal : ''; 
      propAssign($scope, newVal); 
     } 
     return property($scope); 
    }; 
}; 

Il argument.length riflette il numero di valori che vengono passati al getter/setter e sarà 0 su un get e 1 su un set .

Besided che, ho aggiunto la angular.isDefined() come Sumit suggested in a comment per salvare anche ("") valori false e vuoti.

Ecco un updated Plunker