AngularJS - L'attributo value su una casella di testo di input viene ignorato quando viene utilizzato un modello ng?


219

Usando AngularJS se ho impostato un valore di casella di testo di input semplice su qualcosa come "bob" di seguito. Il valore non viene visualizzato se ng-modelviene aggiunto l' attributo.

    <input type="text"
           id="rootFolder"
           ng-model="rootFolders"
           disabled="disabled"
           value="Bob"
           size="40"/>

Qualcuno sa di un semplice modo per aggirare questo input su qualcosa e mantenere il ng-model? Ho provato a utilizzare a ng-bindcon il valore predefinito, ma sembra che non funzioni neanche.

Risposte:


223

Questo è il comportamento desiderato, è necessario definire il modello nel controller, non nella vista.

<div ng-controller="Main">
  <input type="text" ng-model="rootFolders">
</div>


function Main($scope) {
  $scope.rootFolders = 'bob';
}

11
Grazie. Ma in questo caso, il modello è impostato nel controller. E nei documenti angolari, è sempre lo stesso, i dati sono impostati nel controller. Ma il mio controller è in un file JS. Come fare quando su un modulo "modifica"? Come passare i dati del modulo predefinito al controller "la via angolare"?
ByScript

8
Questo non funziona per me, tuttavia l'aggiunta dell'attributo aggiuntivo ng-init mostrato da Mark Rajcok (ng-init = "rootFolders = 'Bob'") funziona bene.
Kaizar Laxmidhar,

E come posso impostare il valore predefinito se ho un campo di input come: <input type = "number" ng-model = "newTransaction [$ index] [user.email]" />?
shish,

188

Vojta ha descritto la "via angolare", ma se hai davvero bisogno di farlo funzionare, @urbanek ha recentemente pubblicato una soluzione alternativa usando ng-init:

<input type="text" ng-model="rootFolders" ng-init="rootFolders='Bob'" value="Bob">

https://groups.google.com/d/msg/angular/Hn3eztNHFXw/wk3HyOl9fhcJ


33
Potrebbe non essere necessaria la parte 'value = "Bob"'.
Mark Rajcok l'

2
+1 ma, come menzionato in uno dei post sulla discussione collegata, dovrebbe essere evitato (poiché logicamente è meno corretto e rende più difficile il test).
0xc0de,

1
Questo metodo funziona bene se si utilizza anche un valore di modello su v1.2. <... ng-init = "rootFolders = someModelAttribute" ...>
dmcqu314

@MarkRajcok, hai così tanti fantastici post su AngularJS su Stack Overflow! Grazie per tutto il tempo che hai dedicato a condividere le tue opinioni con la comunità SO. Sono sicuro di parlare per molti sviluppatori sollevati quando dico che apprezziamo sinceramente tutte le ore che ci hai risparmiato!
Jeremy Moritz,

1
Apprezzo molto la risposta di Mark perché ha risolto il mio problema. Confermo che NON abbiamo bisogno di value="Bob"parte nel tag di input.
Devner,

68

Sovrascrivere la direttiva di input sembra fare il lavoro. Ho apportato alcune piccole modifiche al codice di Dan Hunsaker :

  • Aggiunto un controllo per ngModel prima di provare a utilizzare i $parse().assign()campi senza attributi ngModel.
  • È stato corretto l' assign()ordine dei parametri della funzione.
app.directive('input', function ($parse) {
  return {
    restrict: 'E',
    require: '?ngModel',
    link: function (scope, element, attrs) {
      if (attrs.ngModel && attrs.value) {
        $parse(attrs.ngModel).assign(scope, attrs.value);
      }
    }
  };
});

Questa è la migliore risposta che ho trovato! ... risolve il mio problema in modo elegante. Ho dovuto acquisire un valore su un input nascosto (un token di modulo di Symfony, generato nel server).
PachinSV,

Questa non è solo intelligente, ma la soluzione migliore. Nel mio caso, non posso impostare il valore predefinito di ng-model sul controller perché è un modulo PHP, se la convalida sul lato server fallisce, il modulo si aggiorna e tutto ciò che è in ng-modello andrà perso cancellando il valore di input pure.
Luis Elizondo,

2
Questa sembra la soluzione migliore se vuoi che anche una versione base del tuo modulo HTML funzioni senza JavaScript.
Darren,

Ottima soluzione che in realtà dovrebbe essere un'opzione configurabile non predefinita all'interno dello stesso angolare.
Gracie,

Grazie per la tua soluzione Come risolveresti il ​​problema di input del numero? Viene generato un errore docs.angularjs.org/error/ngModel/numfmt?p0=20.12
mate.gwozdz

21

La via angolare

Il modo angolare corretto per farlo è scrivere un'app a pagina singola, AJAX nel modello di modulo, quindi popolarla dinamicamente dal modello. Il modello non è popolato dal modulo per impostazione predefinita perché il modello è la singola fonte di verità. Invece Angular andrà dall'altra parte e proverà a popolare il modulo dal modello.

Se tuttavia, non hai tempo di ricominciare da capo

Se hai un'app scritta, ciò potrebbe comportare alcune modifiche architettoniche piuttosto pesanti. Se stai cercando di utilizzare Angular per migliorare un modulo esistente, piuttosto che costruire un'intera app per pagina singola da zero, puoi estrarre il valore dal modulo e memorizzarlo nell'ambito al momento del collegamento usando una direttiva. Angular assocerà quindi il valore nell'ambito nell'ambito al modulo e lo manterrà sincronizzato.

Usando una direttiva

È possibile utilizzare una direttiva relativamente semplice per estrarre il valore dal modulo e caricarlo nell'ambito corrente. Qui ho definito una direttiva initFromForm.

var myApp = angular.module("myApp", ['initFromForm']);

angular.module('initFromForm', [])
  .directive("initFromForm", function ($parse) {
    return {
      link: function (scope, element, attrs) {
        var attr = attrs.initFromForm || attrs.ngModel || element.attrs('name'),
        val = attrs.value;
        if (attrs.type === "number") {val = parseInt(val)}
        $parse(attr).assign(scope, val);
      }
    };
  });

Puoi vedere che ho definito un paio di fallback per ottenere il nome di un modello. È possibile utilizzare questa direttiva insieme alla direttiva ngModel o legare a qualcosa di diverso da $ scope se si preferisce.

Usalo in questo modo:

<input name="test" ng-model="toaster.test" value="hello" init-from-form />
{{toaster.test}}

Nota che funzionerà anche con textareas e seleziona i menu a discesa.

<textarea name="test" ng-model="toaster.test" init-from-form>hello</textarea>
{{toaster.test}}

Ecco un modulo compresso che implementa una soluzione simile a quella descritta qui github.com/platanus/angular-keep-values
Agustin,

1
Ottima soluzione, ma funzionerà solo con input="text". Se ne hai uno number, il modello non è di tipo number docs.angularjs.org/error/ngModel/numfmt?p0=333
smoksnes

2
Per supportare i numeri è possibile aggiungere if (attrs.type === "number") val = parseInt(val);
smoksnes il

@smoksnes - hai assolutamente ragione. Ho aggiornato la risposta :)
superluminario,

7

Aggiornamento: la mia risposta originale prevedeva che il controller contenga codice DOM-based, che rompe le convenzioni angolari a favore dell'HTML. @dmackerman ha menzionato le direttive in un commento sulla mia risposta, e mi è mancato completamente fino ad ora. Con questo input, ecco il modo giusto per farlo senza rompere le convenzioni angolari o HTML:


C'è anche un modo per ottenere entrambi: prendi il valore dell'elemento e usalo per aggiornare il modello in una direttiva:

<div ng-controller="Main">
    <input type="text" id="rootFolder" ng-model="rootFolders" disabled="disabled" value="Bob" size="40" />
</div>

e poi:

app.directive('input', ['$parse', function ($parse) {
    return {
        restrict: 'E',
        require: '?ngModel',
        link: function (scope, element, attrs) {
            if(attrs.value) {
                $parse(attrs.ngModel).assign(scope, attrs.value);
            }
        }
    };
}]);

Ovviamente puoi modificare la suddetta direttiva per fare di più con l' valueattributo prima di impostare il modello sul suo valore, incluso l'uso $parse(attrs.value, scope)per trattare l' valueattributo come un'espressione angolare (anche se probabilmente utilizzerei un attributo [personalizzato] diverso per quello, personalmente, quindi gli attributi HTML standard vengono costantemente trattati come costanti).

Inoltre, vi è una domanda analoga su Rendere i dati forniti come modello al modello ng che potrebbero anche essere di interesse.


Non dovresti fare alcuna manipolazione / scoperta DOM nei tuoi controller. Dovrebbe usare invece una direttiva.
dmackerman,

2
Ho menzionato esplicitamente tale inconveniente nella mia risposta. Non dovresti , ma puoi . Tutto dipende dal fatto che trovi più importante seguire le convenzioni di Angular o HTML. Perché Angular rompe HTML.
Dan Hunsaker,

3
Oh, sono un manichino. Mi mancava del tutto l'uso della direttiva. Risposta aggiornata di conseguenza. Le più sincere scuse per essere stato un idiota per te, @dmackerman.
Dan Hunsaker,

Grazie per la direttiva! Mi ha dato le idee per candidarmi in un progetto su cui sto lavorando dove ho generato un lato server di contenuti e quindi ho dovuto usarlo come modello nel client.
ggalmazor,

Sono contento di poterti aiutare. Ovviamente, in generale, ti consigliamo di creare il contenuto sul lato server come JSON e far sì che la tua app manipoli il modello in base a quello, ma a volte è utile avere altre opzioni, e questo è solo uno.
Dan Hunsaker,

7

Se usi la direttiva ngModel di AngularJs, ricorda che il valore valuedell'attributo non si lega al campo ngModel . Devi iniziarlo da solo e il modo migliore per farlo, è

<input type="text"
       id="rootFolder"
       ng-init="rootFolders = 'Bob'"
       ng-model="rootFolders"
       disabled="disabled"
       value="Bob"
       size="40"/>

Sembra strano iniziarlo nella direttiva / markup invece che nel controller.
random_user_name

5

Questa è una leggera modifica alle risposte precedenti ...

Non è necessario $ parse

angular.directive('input', [function () {
  'use strict';

  var directiveDefinitionObject = {
    restrict: 'E',
    require: '?ngModel',
    link: function postLink(scope, iElement, iAttrs, ngModelController) {
      if (iAttrs.value && ngModelController) {
        ngModelController.$setViewValue(iAttrs.value);
      }
    }
  };

  return directiveDefinitionObject;
}]);

tieni presente che ngModelController. $ setViewValue cambierà lo stato del modello in sporco e da incontaminato a falso, il che influirà anche sullo stato del modulo che può essere doloroso un po 'di tempo.
Atul Chaudhary,

2

Ciao, puoi provare i metodi seguenti con l'inizializzazione del modello.

Qui puoi inizializzare ng-model della casella di testo in due modi

- Con l'uso di ng-init

- Con l'uso di $ scope in js

<!doctype html>
 <html >
 <head>
        <title>Angular js initalize with ng-init and scope</title>
        <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>
</head>
<body ng-app="app" >
    <h3>Initialize value with ng-init</h3>
    <!-- Initlialize model values with ng-init -->
    <div ng-init="user={fullname:'Bhaskar Bhatt',email:'bhatt.bhaskar88@gmail.com',address:'Ahmedabad'};">
        Name : <input type="text" ng-model="user.fullname" /><br/>
        Email : <input type="text" ng-model="user.email" /><br/>
        Address:<input type="text" ng-model="user.address" /><br/>

    </div>  
    <!-- initialize with js controller scope -->
    <h3>Initialize with js controller</h3>

    <div  ng-controller="alpha">
        Age:<input type="text" name="age" ng-model="user.age" /><br/>
        Experience : <input type="text" name="experience" ng-model="user.exp" /><br/>
        Skills : <input type="text" name="skills" ng-model="user.skills" /><br/>
    </div>  

</body> 
<script type="text/javascript">
        angular.module("app",[])
        .controller("alpha",function($scope){
            $scope.user={};
            $scope.user.age=27;
            $scope.user.exp="4+ years";
            $scope.user.skills="Php,javascript,Jquery,Ajax,Mysql";
        });

     </script>
 </html>                

0

Il problema è che devi impostare ng-model sull'elemento parent su dove vuoi impostare ng-value / value. Come menzionato da Angular:

Viene utilizzato principalmente sugli input [radio] e sugli elementi opzione, in modo che quando l'elemento è selezionato, ngModel di quell'elemento (o il suo elemento padre selezionato) è impostato sul valore associato.

Ad esempio: questo è un codice eseguito:

<div class="col-xs-12 select-checkbox" >
<label style="width: 18em;" ng-model="vm.settingsObj.MarketPeers">
  <input name="radioClick" type="radio"  ng-click="vm.setPeerGrp('market');" 
         ng-value="vm.settingsObj.MarketPeers" 
         style="position:absolute;margin-left: 9px;">
  <div style="margin-left: 35px;color: #717171e8;border-bottom: 0.5px solid #e2e2e2;padding-bottom: 2%;">Hello World</div>
</label>
</div>

Nota: in questo caso sopra ho avuto la risposta JSON al modello ng e il valore, sto solo aggiungendo un'altra proprietà all'oggetto JS come "MarketPeers". Quindi il modello e il valore possono dipendere dalla necessità, ma penso che questo processo aiuterà, per avere sia ng-modello che valore ma non averli sullo stesso elemento.


0

Ho avuto un problema simile. Non sono stato in grado di utilizzare value="something"per visualizzare e modificare. Ho dovuto usare il comando seguente all'interno del mio <input>modello lungo dichiarato.

[(ngModel)]=userDataToPass.pinCode

Dove ho l'elenco dei dati nell'oggetto userDataToPasse l'elemento che devo visualizzare e modificare è pinCode.

Per lo stesso, ho fatto riferimento a questo video di YouTube


Per questo, l'OP utilizza AngularJS, il riferimento video YT utilizza Angular 4.
Chris22
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.