AngularJS - Das Wertattribut in einem Eingabetextfeld wird ignoriert, wenn ein ng-Modell verwendet wird.

218

Verwenden von AngularJS, wenn ich einen einfachen Eingabetextfeldwert auf "bob" unten setze. Der Wert wird nicht angezeigt, wenn das ng-modelAttribut hinzugefügt wird.

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

Kennt jemand eine einfache Lösung, um diese Eingabe auf etwas zu setzen und die ng-model? Ich habe versucht, a ng-bindmit dem Standardwert zu verwenden, aber das scheint auch nicht zu funktionieren.

Hallo Welt
quelle

Antworten:

223

Das ist gewünschtes Verhalten, Sie sollten das Modell in der Steuerung definieren, nicht in der Ansicht.

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


function Main($scope) {
  $scope.rootFolders = 'bob';
}
Vojta
quelle
11
Vielen Dank. In diesem Fall wird das Modell jedoch in der Steuerung eingestellt. Und in den Angular-Dokumenten ist es immer dasselbe, Daten werden in der Steuerung festgelegt. Aber mein Controller befindet sich in einer JS-Datei. Wie geht man in einem "Bearbeitungs" -Formular vor? Wie werden Standardformulardaten "im Winkel" an den Controller übergeben?
ByScripts
8
Dies funktioniert bei mir nicht, aber das Hinzufügen des zusätzlichen Attributs ng-init von Mark Rajcok (ng-init = "rootFolders = 'Bob'") funktioniert einwandfrei.
Kaizar Laxmidhar
Und wie setze ich den Standardwert, wenn ich ein Eingabefeld habe wie: <input type = "number" ng-model = "newTransaction [$ index] [user.email]" />?
Shish
188

Vojta hat den "Angular Way" beschrieben, aber wenn Sie diese Funktion wirklich benötigen, hat @urbanek kürzlich eine Problemumgehung mit ng-init veröffentlicht:

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

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

Mark Rajcok
quelle
33
Möglicherweise benötigen Sie den Teil 'value = "Bob" nicht.
Mark Rajcok
2
+1 aber, wie in einem der Beiträge in der verlinkten Diskussion erwähnt, sollte es vermieden werden (da es logischerweise weniger korrekt ist und das Testen schwieriger macht).
0xc0de
1
Diese Methode funktioniert einwandfrei, wenn Sie in Version 1.2 auch einen Modellwert verwenden. <... ng-init = "rootFolders = someModelAttribute" ...>
dmcqu314
@ MarkRajcok, du hast so viele tolle AngularJS-Postings auf Stack Overflow! Vielen Dank für all die Zeit, die Sie darauf verwendet haben, Ihre Erkenntnisse mit der SO-Community zu teilen. Ich bin sicher, ich spreche für viele erleichterte Entwickler, wenn ich sage, dass wir all die Stunden, die Sie uns gespart haben, aufrichtig schätzen!
Jeremy Moritz
1
Ich schätze Marks Antwort sehr, da dies mein Problem gelöst hat. Ich bestätige, dass wir KEINEN value="Bob"Teil des Eingabe-Tags benötigen .
Devner
68

Das Überschreiben der Eingaberichtlinie scheint die Aufgabe zu erfüllen. Ich habe einige kleinere Änderungen am Code von Dan Hunsaker vorgenommen :

  • Es wurde eine Prüfung für ngModel hinzugefügt, bevor versucht wird, $parse().assign()Felder ohne ngModel-Attribute zu verwenden.
  • assign()Die Reihenfolge der Funktionsparameter wurde korrigiert.
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);
      }
    }
  };
});
Ivan Breet
quelle
Dies ist die beste Antwort, die ich gefunden habe! ... löst mein Problem auf elegante Weise. Ich musste einen Wert für eine versteckte Eingabe erfassen (ein Symfony-Formular-Token, das auf dem Server generiert wurde).
PachinSV
Dies ist nicht nur clever, sondern auch die beste Lösung. In meinem Fall kann ich den Standardwert von ng-model auf dem Controller nicht festlegen, da es sich um ein PHP-Formular handelt. Wenn die serverseitige Validierung fehlschlägt, wird das Formular aktualisiert und alles, was sich in ng-model befindet, geht verloren, wenn der Eingabewert gelöscht wird auch.
Luis Elizondo
2
Dies scheint die beste Lösung zu sein, wenn Sie möchten, dass eine Basisversion Ihres HTML-Formulars auch ohne JavaScript funktioniert.
Darren
Hervorragende Lösung, die eigentlich eine nicht standardmäßig konfigurierbare Option innerhalb des Winkels selbst sein sollte.
Gracie
Vielen Dank für Ihre Lösung. Wie würden Sie das Problem der Zahleneingabe lösen? Es wird ein Fehler ausgelöst docs.angularjs.org/error/ngModel/numfmt?p0=20.12
mate.gwozdz
21

Der eckige Weg

Die richtige Methode für Angular besteht darin, eine einzelne Seiten-App, AJAX, in die Formularvorlage zu schreiben und sie dann dynamisch aus dem Modell zu füllen. Das Modell wird standardmäßig nicht aus dem Formular ausgefüllt, da das Modell die einzige Quelle der Wahrheit ist. Stattdessen geht Angular in die andere Richtung und versucht, das Formular aus dem Modell zu füllen.

Wenn Sie jedoch keine Zeit haben, von vorne zu beginnen

Wenn Sie eine App geschrieben haben, kann dies zu erheblichen architektonischen Änderungen führen. Wenn Sie versuchen, Angular zu verwenden, um ein vorhandenes Formular zu verbessern, anstatt eine einzelne App für eine einzelne Seite von Grund auf neu zu erstellen, können Sie den Wert aus dem Formular abrufen und mithilfe einer Direktive zum Zeitpunkt der Verknüpfung im Bereich speichern. Angular bindet dann den Wert im Bereich wieder an das Formular und hält ihn synchron.

Verwendung einer Direktive

Sie können eine relativ einfache Anweisung verwenden, um den Wert aus dem Formular abzurufen und in den aktuellen Bereich zu laden. Hier habe ich eine initFromForm-Direktive definiert.

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);
      }
    };
  });

Sie können sehen, dass ich einige Fallbacks definiert habe, um einen Modellnamen zu erhalten. Sie können diese Direktive in Verbindung mit der ngModel-Direktive verwenden oder an etwas anderes als $ scope binden, wenn Sie dies bevorzugen.

Verwenden Sie es so:

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

Beachten Sie, dass dies auch mit Textbereichen funktioniert, und wählen Sie Dropdowns aus.

<textarea name="test" ng-model="toaster.test" init-from-form>hello</textarea>
{{toaster.test}}
überleuchtet
quelle
Hier ist ein gepacktes Modul, das eine Lösung implementiert, die der hier beschriebenen ähnlich ist. Github.com/platanus/angular-keep-values
Agustin
1
Tolle Lösung, aber es wird nur funktionieren input="text". Wenn Sie eine haben number, wird es werfen Modell ist nicht vom Typ number docs.angularjs.org/error/ngModel/numfmt?p0=333
smoksnes
2
Um Zahlen zu unterstützen, können Sie hinzufügen if (attrs.type === "number") val = parseInt(val);
smoksnes
@smoksnes - du bist absolut richtig. Ich habe die Antwort aktualisiert :)
Superluminary
7

Update: Meine ursprüngliche Antwort bestand darin, dass der Controller DOM-fähigen Code enthält, der gegen Angular-Konventionen zugunsten von HTML verstößt. @dmackerman erwähnte Anweisungen in einem Kommentar zu meiner Antwort, und das habe ich bis jetzt völlig verpasst. Mit diesem Eingang, hier ist der richtige Weg , dies zu tun , ohne Eckige zu brechen oder HTML - Konventionen:


Es gibt auch eine Möglichkeit, beides zu erhalten: Nehmen Sie den Wert des Elements und aktualisieren Sie damit das Modell in einer Direktive:

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

und dann:

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);
            }
        }
    };
}]);

Sie können die obige Direktive natürlich ändern, um mehr mit dem valueAttribut zu tun , bevor Sie das Modell auf seinen Wert setzen, einschließlich der Verwendung $parse(attrs.value, scope), um das valueAttribut als Winkelausdruck zu behandeln (obwohl ich persönlich wahrscheinlich ein anderes [benutzerdefiniertes] Attribut dafür verwenden würde). Daher werden die Standard-HTML-Attribute konsistent als Konstanten behandelt.

Es gibt auch eine ähnliche Frage bei der Bereitstellung von Daten für das ng-Modell, die ebenfalls von Interesse sein können.

Dan Hunsaker
quelle
Sie sollten keine DOM-Manipulation / -Erkennung in Ihren Controllern durchführen. Sollte stattdessen eine Direktive verwenden.
Dmackerman
2
Ich habe diesen Nachteil in meiner Antwort ausdrücklich erwähnt. Du solltest nicht , aber du kannst . Es hängt alles davon ab, ob es für Sie wichtiger ist, die Konventionen von Angular oder HTML zu befolgen. Weil Angular HTML kaputt macht.
Dan Hunsaker
3
Oh, ich bin ein Dummy. Ich habe das bisschen über die Verwendung einer Direktive völlig verpasst. Antwort entsprechend aktualisiert. Mit freundlichen Grüßen entschuldigen Sie, dass Sie ein Idiot sind, @dmackerman.
Dan Hunsaker
Danke für die Anweisung! Es gab mir Ideen, mich in einem Projekt zu bewerben, an dem ich arbeite, wo ich eine Content-Server-Seite generiere und es dann als mein Modell im Client verwenden muss.
Galgazor
Froh, dass ich helfen konnte. Im Allgemeinen möchten Sie natürlich Ihren serverseitigen Inhalt als JSON erstellen und Ihre App das Modell darauf basierend manipulieren lassen, aber manchmal ist es nützlich, andere Optionen zu haben, und dies ist nur eine.
Dan Hunsaker
7

Wenn Sie die ngModel-Direktive von AngularJs verwenden, denken Sie daran, dass der Wert des valueAttributs nicht an das ngModel-Feld gebunden ist. Sie müssen es selbst initiieren, und der beste Weg, dies zu tun, ist

<input type="text"
       id="rootFolder"
       ng-init="rootFolders = 'Bob'"
       ng-model="rootFolders"
       disabled="disabled"
       value="Bob"
       size="40"/>
Hazarapet Tunanyan
quelle
Es fühlt sich seltsam an, es in der Direktive / im Markup anstelle des Controllers zu initiieren.
random_user_name
5

Dies ist eine geringfügige Änderung der früheren Antworten ...

$ Parse ist nicht erforderlich

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;
}]);
dale.lotts
quelle
Denken Sie daran, dass ngModelController. $ setViewValue den Modellstatus in "schmutzig" und "makellos" in "falsch" ändert, was sich auch auf den Formularstatus auswirkt, der einige Zeit schmerzhaft sein kann.
Atul Chaudhary
2

Hallo, Sie können unten Methoden mit Initialisierung des Modells versuchen.

Hier können Sie das ng-Modell des Textfelds auf zwei Arten initialisieren

- Bei Verwendung von ng-init

- Bei Verwendung von $ 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:'[email protected]',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>                
Bhaskar Bhatt
quelle
0

Das Problem ist, dass Sie das ng-Modell auf das übergeordnete Element setzen müssen, auf das Sie den ng-Wert / Wert setzen möchten. Wie von Angular erwähnt:

Es wird hauptsächlich für Eingabe- [Radio] und Optionselemente verwendet, sodass bei Auswahl des Elements das ngModel dieses Elements (oder seines ausgewählten übergeordneten Elements) auf den gebundenen Wert gesetzt wird.

Beispiel: Dies ist ein ausgeführter Code:

<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>

Hinweis: In diesem obigen Fall hatte ich bereits die JSON-Antwort auf das ng-Modell und den Wert. Ich füge dem JS-Objekt lediglich eine weitere Eigenschaft als "MarketPeers" hinzu. Das Modell und der Wert können also je nach Bedarf abhängen, aber ich denke, dieser Prozess wird helfen, sowohl ng-Modell als auch Wert zu haben, aber sie nicht auf demselben Element zu haben.

sg28
quelle
0

Ich hatte ein ähnliches Problem. Ich konnte nicht value="something"zum Anzeigen und Bearbeiten verwenden. Ich musste den folgenden Befehl in meinem <input>zusammen mit dem deklarierten Modell verwenden.

[(ngModel)]=userDataToPass.pinCode

Wo ich die Liste der Daten im Objekt userDataToPassund das Element habe, das ich anzeigen und bearbeiten muss, istpinCode .

Aus dem gleichen Grund habe ich auf dieses YouTube-Video verwiesen

tkrloltkr
quelle
Für dieses HowTo verwendet das OP AngularJS, Ihre YT-
Videoreferenz