/ / AngularJS ng-model non esegue l'associazione dati bidirezionale: angularjs, associazione dati, angularjs-scope

AngularJS ng-model non esegue l'associazione dati bidirezionale: angularjs, associazione dati, ambito angularjs

Ho un'etichetta con una casella di input in questo modo:

  <label class="item item-input">
<input type="text" data-ng-model="description" placeholder="Add a Description!">
</label>

Come puoi vedere questa casella di input è legata all'ambito "descrizione"

Nel mio controller ho qualcosa sulla falsariga di questo:

$scope.description = "";
$scope.submit = function() {
console.log($scope.description);
};

Nel mio HTML ho anche questa riga:

  <div ng-show="description.length <= maxChars">{{description}}</div>

La funzione di invio viene chiamata quando l'utente colpisceil pulsante di invio dopo aver digitato nella casella di input. La descrizione viene visualizzata correttamente. Quando l'utente digita nella casella di input, la descrizione viene aggiornata nell'HTML ma NON nel controller.

Ho la sensazione che abbia qualcosa a che fare conl'impostazione della descrizione su una stringa vuota ma viene chiaramente aggiornata per quanto riguarda l'HTML. Ma mantiene console.logging e stringa vuota a prescindere.

Per farlo funzionare, ho dovuto passare la descrizione direttamente nella funzione di invio (e anche aggiornare la funzione di conseguenza):

<button class="button button-positive" data-ng-click="submit(description)">Submit</button>

Questo è completamente inutile poiché Angular dovrebbe eseguire automaticamente l'associazione dati bidirezionale ma non lo è.

Qualcuno ha qualche idea?

Qualsiasi aiuto sarebbe apprezzato.

MODIFICARE:

Ecco l'HTML completo a grande richiesta.

<ion-view title="Moments" id="page2">
<ion-content padding="true" class="has-header">
<img src="/images/{{picture}}" height="300px" width="100%"> </img>
<div class="row">
<div ng-show="description.length > maxChars" style= "color: red">{{description}}</div>
<div ng-show="description.length <= maxChars">{{description}}</div>
</div>
<div class="row" ng-if="description">
<div ng-show="description.length > maxChars" style= "color: red">{{description.length}} / {{maxChars}}</div>
<div ng-show="description.length <= maxChars" style= "color: green">{{description.length}} / {{maxChars}}</div>
</div>
<div class="row">
<div class="col">
<label class="item item-input">
<input type="text" data-ng-model="description" placeholder="Add a Description!">
</label>
</div>
<button style="margin-right: 5px" class="col col-10 button button-positive" data-ng-click="checkDescription(description)">OK</button>
</div>
<div class="row">
<div class="col"><ion-checkbox data-ng-change="changeLocation()" data-ng-model="location">Show Location</ion-checkbox></div>
</div>
<div class="row">
<div class="button-bar">
<button class="button button-assertive" data-ng-click="cancel()">Cancel</button>
<button class="button button-positive" data-ng-click="submit(description)">Submit</button>
</div>
</div>
</ion-content>
</ion-view>

Sono anche consapevole che in questa domanda il submitla funzione non accetta parametri. È così che vorrei che fosse. Attualmente il mio pulsante di invio richiede un parametro (la descrizione). Questo non dovrebbe essere necessario. Anche io sto riscontrando lo stesso problema con la funzione "checkDescription". Anche quella funzione non dovrebbe avere parametri ma, ancora una volta, sono costretto a passare la descrizione direttamente alla funzione, cosa che preferisco non fare.

risposte:

1 per risposta № 1

Sintesi:

In AngularJS, un ambito figlio normalmente eredita in modo prototipico dal suo ambito padre. Un'eccezione a questa regola è una direttiva che usa scope: { ... } -- questo crea un ambito "isolato" che non lo faereditare prototipicamente.(e direttiva con transclusione) Questo costrutto viene spesso utilizzato quando si crea una direttiva "componente riutilizzabile". Nelle direttive, l'ambito padre viene utilizzato direttamente per impostazione predefinita, il che significa che qualsiasi modifica nella direttiva che proviene dall'ambito padre cambierà anche nell'ambito padre. Se imposti scope:true (invece di ambito: { ... }), per tale direttiva verrà utilizzata l'ereditarietà prototipo.

L'ereditarietà dell'ambito è normalmente semplice e spesso non è nemmeno necessario sapere che sta accadendo... finché non si prova Associazione dati a 2 vie (cioè, elementi di forma, modello ng) ad un primitivo (per esempio., numero, stringa, booleano) definito nell'ambito padre dall'interno dell'ambito figlio. Non funziona nel modo in cui la maggior parte delle persone si aspetta che funzioni. Quello che succede è che l'ambito figlio ottiene la propria proprietà che nasconde/ombreggia la proprietà genitore con lo stesso nome. Questo non è qualcosa che sta facendo AngularJS: ecco come il prototipo JavaScript l'ereditarietà funziona. I nuovi sviluppatori AngularJS spesso non se ne rendono conto ng-repeat, ng-switch, ng-view, ng-include e ng-if tutti creano nuovi ambiti figlio, quindi il problema si presenta spesso quando sono coinvolte queste direttive. (Vedere questo esempio per una rapida illustrazione del problema.)

Questo problema con le primitive può essere facilmente evitato seguendo la "best practice" di avere sempre un punto "." nei tuoi modelli ng – guarda 3 minuti che valgono. Misko dimostra il problema di associazione primitivo con ng-switch.

--AngularJS Wiki -- The Nuances of Scope Prototypal Inheritance


Ho provato a fare il "." notazione nel mio ambito ma ogni volta che provo a fare riferimento ad essa in questo modo:

$scope.moment.description = "";

Dice "Impossibile leggere la "descrizione" della proprietà di undefined.

Il codice deve creare l'oggetto prima di assegnare un valore a una proprietà:

$scope.moment = {};
$scope.moment.description = "";

//OR

$scope.moment = { description: "" };

0 per risposta № 2

Per tenere traccia dell'aggiornamento del valore, puoi utilizzare $watch,

scope.$watch("description", function(newValue, oldValue) {
console.log(newValue);
});