AngularJS sendet keinen versteckten Feldwert


192

Für einen bestimmten Anwendungsfall muss ich ein einzelnes Formular auf "alte Weise" einreichen. Das heißt, ich benutze ein Formular mit action = "". Die Antwort wird gestreamt, daher lade ich die Seite nicht neu. Ich bin mir völlig bewusst, dass eine typische AngularJS-App kein Formular auf diese Weise senden würde, aber bisher habe ich keine andere Wahl.

Trotzdem habe ich versucht, einige versteckte Felder aus Angular zu füllen:

<input type="hidden" name="someData" ng-model="data" /> {{data}}

Bitte beachten Sie, dass der korrekte Wert in den Daten angezeigt wird.

Das Formular sieht aus wie ein Standardformular:

<form id="aaa" name="aaa" action="/reports/aaa.html" method="post">
...
<input type="submit" value="Export" />
</form>

Wenn ich auf Senden drücke, wird kein Wert an den Server gesendet. Wenn ich das Eingabefeld in "Text" ändere, funktioniert es wie erwartet. Ich gehe davon aus, dass das ausgeblendete Feld nicht wirklich ausgefüllt ist, während das Textfeld aufgrund der bidirektionalen Bindung tatsächlich angezeigt wird.

Irgendwelche Ideen, wie ich ein verstecktes Feld einreichen kann, das von AngularJS ausgefüllt wird?


4
Hmm ... wie wäre es mit Text display: none;? Es ist hässlich. Angular ignoriert versteckte Elemente.
TymeJV

Setzen Sie das als Antwort @tymeJV!
Jeroen Ingelbrecht

7
Ich verwende die folgende Syntax, um einen Wert zu binden : <input type="hidden" required ng-model="data.userid" ng-init="data.userid=pivot.id" /> . Dies ist möglicherweise nicht die richtige Vorgehensweise, funktioniert aber für mich.
John P

Antworten:


287

Sie können keine Doppelbindung mit ausgeblendetem Feld verwenden. Die Lösung besteht darin, Klammern zu verwenden:

<input type="hidden" name="someData" value="{{data}}" /> {{data}}

BEARBEITEN: Siehe diesen Thread auf Github: https://github.com/angular/angular.js/pull/2574

BEARBEITEN:

Seit Angular 1.2 können Sie die Anweisung 'ng-value' verwenden, um einen Ausdruck an das value-Attribut der Eingabe zu binden. Diese Anweisung sollte mit Eingabe-Radio oder Kontrollkästchen verwendet werden, funktioniert jedoch gut mit versteckten Eingaben.

Hier ist die Lösung mit ng-value:

<input type="hidden" name="someData" ng-value="data" />

Hier ist eine Geige mit ng-Wert und versteckter Eingabe: http://jsfiddle.net/6SD9N


Genial. Vielen Dank. Ich wollte fast das Textfeld verstecken, aber jetzt denke ich, dass dies eine großartige Problemumgehung ist.
Christian

22
Toll. Außerdem können Sie ng-value = "modelName" verwenden, um dies ohne Klammern zu tun.
Jonathan

2
Das ist richtig, seit Angular 1.2 können Sie ng-value verwenden, um einen Ausdruck an das value-Attribut zu binden. Die Antwort ist aktuell.
Mickael

Benötigen Sie wirklich ein verstecktes Feld mehr, wenn Sie AngularJS verwenden? Bei ngSubmit drücken Sie einen Controller, alle Ihre Daten sind für den Zugriff vollständig sichtbar, und Sie senden sie alle über einen $ http-Dienst.
Mtpultz

3
Vielen Dank. Die Tatsache, dass das ng-Modell nicht für versteckte Eingaben verwendet werden kann, sollte in AngularJS IMO dokumentiert werden.
Yoonchee

47

Sie können immer ein type=textund verwenden, display:none;da Angular versteckte Elemente ignoriert. Wie OP sagt, würden Sie dies normalerweise nicht tun, aber dies scheint ein Sonderfall zu sein.

<input type="text" name="someData" ng-model="data" style="display: none;"/>

Vielen Dank! Ich dachte in die gleiche Richtung, aber ich musste einfach die {{}} Lösung von Mickael bevorzugen.
Christian

1
clevere / intelligente Lösung
ImranNaqvi

8

In der Steuerung:

$scope.entityId = $routeParams.entityId;

In der Ansicht:

<input type="hidden" name="entityId" ng-model="entity.entityId" ng-init="entity.entityId = entityId" />

1
Guter Punkt ... Ich würde dies beim nächsten Mal lieber nur im Controller tun
meffect

Ich verliebe mich in ng-init
ImranNaqvi

Nein. In der Schleife macht es viel Ärger und weist allen den letzten Wert zu, entityIdwenn entityIdes sich um ein Array handelt
ImranNaqvi

4

Ich habe eine nette Lösung gefunden, die Mike für sapiensworks geschrieben hat . Es ist so einfach wie die Verwendung einer Direktive, die auf Änderungen an Ihrem Modell achtet:

.directive('ngUpdateHidden',function() {
    return function(scope, el, attr) {
        var model = attr['ngModel'];
        scope.$watch(model, function(nv) {
            el.val(nv);
        });
    };
})

und binden Sie dann Ihre Eingabe:

<input type="hidden" name="item.Name" ng-model="item.Name" ng-update-hidden />

Die von tymeJV bereitgestellte Lösung könnte jedoch besser sein, da versteckte Eingaben kein Änderungsereignis in Javascript auslösen, wie yycorman in diesem Beitrag sagte. Wenn Sie also den Wert über ein jQuery-Plugin ändern, funktioniert dies weiterhin.

Bearbeiten Ich habe die Direktive geändert, um einen neuen Wert wieder auf das Modell anzuwenden, wenn ein Änderungsereignis ausgelöst wird, sodass es als Eingabetext funktioniert.

.directive('ngUpdateHidden', function () {
    return {
        restrict: 'AE', //attribute or element
        scope: {},
        replace: true,
        require: 'ngModel',
        link: function ($scope, elem, attr, ngModel) {
            $scope.$watch(ngModel, function (nv) {
                elem.val(nv);
            });
            elem.change(function () { //bind the change event to hidden input
                $scope.$apply(function () {
                    ngModel.$setViewValue(  elem.val());
                });
            });
        }
    };
})

Wenn Sie also ein $("#yourInputHidden").trigger('change')Ereignis mit jQuery auslösen , wird auch das gebundene Modell aktualisiert.


Hat jemand anderes Probleme, diese Lösung zum Laufen zu bringen? Das Problem ist, dass der Parameter ngModel undefiniert ist, wenn die Direktive analysiert und ausgeführt wird, sodass die $ watch nicht hinzugefügt wird.
icfantv

OK. Es scheint, dass das Problem darin besteht, dass der vierte Parameter ngModel ein Objekt ist, während das Beispiel, auf das über den Link bei sapiensworks verwiesen wird, den Zeichenfolgenwert des Attributs ng-model über attr ['ngModel'] abruft und diesen dann an die Uhr weitergibt. Ich kann bestätigen, dass diese Änderung das Problem mit der Uhr behebt.
icfantv

Hier gibt es noch ein anderes Problem. jQuery löst kein Änderungsereignis aus, wenn Sie den Wert eines ausgeblendeten Eingabefelds programmgesteuert ändern. Wenn ich also $ (hidden_input_elt) .val ("snoopy") sage, muss ich auch .change () hinzufügen, damit das Änderungsereignis ausgelöst wird. Das Problem dabei ist, dass Angular sich über den oben genannten $ scope.apply () beschwert, da er sich bereits in einem $ apply befindet und bereits ausgeführt wird. Die Lösung besteht darin, den $ scope. $ Apply in der obigen Änderungsfunktion zu entfernen und einfach ngModel aufzurufen. $ SetViewValue (...).
icfantv

2

Wir haben ein seltsames Verhalten bei diesem versteckten Wert () festgestellt und können ihn nicht zum Laufen bringen.

Nach dem Herumspielen haben wir festgestellt, dass der beste Weg darin besteht, den Wert im Controller selbst nach dem Formularbereich zu definieren.

.controller('AddController', [$scope, $http, $state, $stateParams, function($scope, $http, $state, $stateParams) {

    $scope.routineForm = {};
    $scope.routineForm.hiddenfield1 = "whatever_value_you_pass_on";

    $scope.sendData = function {

// JSON http post action to API 
}

}])

1

Ich habe dies erreicht über -

 <p style="display:none">{{user.role="store_user"}}</p>

1

Aktualisieren Sie die Antwort von @tymeJV, z.

 <div style="display: none">
    <input type="text" name='price' ng-model="price" ng-init="price = <%= @product.price.to_s %>" >
 </div>

0

Ich hatte das gleiche Problem, ich muss wirklich einen Schlüssel von meinem JSP an das Java-Skript senden. Es dauert ungefähr 4 Stunden oder mehr meines Tages, um es zu lösen.

Ich füge dieses Tag in mein JavaScript / JSP ein:

 $scope.sucessMessage = function (){  
    	var message =     ($scope.messages.sucess).format($scope.portfolio.name,$scope.portfolio.id);
    	$scope.inforMessage = message;
    	alert(message);  
}
 

String.prototype.format = function() {
    var formatted = this;
    for( var arg in arguments ) {
        formatted = formatted.replace("{" + arg + "}", arguments[arg]);
    }
    return formatted;
};
<!-- Messages definition -->
<input type="hidden"  name="sucess"   ng-init="messages.sucess='<fmt:message  key='portfolio.create.sucessMessage' />'" >

<!-- Message showed affter insert -->
<div class="alert alert-info" ng-show="(inforMessage.length > 0)">
    {{inforMessage}}
</div>

<!-- properties
  portfolio.create.sucessMessage=Portf\u00f3lio {0} criado com sucesso! ID={1}. -->

Das Ergebnis war: Portfólio 1 criado com sucesso! ID = 3.

Freundliche Grüße


0

Nur für den Fall, dass noch jemand damit zu kämpfen hat, hatte ich ein ähnliches Problem, als ich versuchte, die Benutzersitzung / Benutzer-ID auf mehrseitigem Formular zu verfolgen

Ich habe das durch Hinzufügen behoben

.when ("/ q2 /: uid" im Routing:

    .when("/q2/:uid", {
        templateUrl: "partials/q2.html",
        controller: 'formController',
        paramExample: uid
    })

Und fügte dies als verstecktes Feld hinzu, um Parameter zwischen Webform-Seiten zu übergeben

<< input type = "hidden" erforderlich ng-model = "formData.userid" ng-init = "formData.userid = uid" />

Ich bin neu bei Angular, bin mir also nicht sicher, ob es die bestmögliche Lösung ist, aber es scheint jetzt für mich in Ordnung zu sein


0

Weisen Sie den Wert direkt dem Modell im data-ng-valueAttribut zu. Da Angular Interpreter versteckte Felder als Teil von ngModel nicht erkennt.

<input type="hidden" name="pfuserid" data-ng-value="newPortfolio.UserId = data.Id"/>

0

Ich benutze ein klassisches Javascript, um den Wert auf versteckte Eingaben zu setzen

$scope.SetPersonValue = function (PersonValue)
{
    document.getElementById('TypeOfPerson').value = PersonValue;
    if (PersonValue != 'person')
    {
        document.getElementById('Discount').checked = false;
        $scope.isCollapsed = true;
    }
    else
    {
        $scope.isCollapsed = false;
    }
}

0

Der folgende Code funktioniert für diese IFF in derselben Reihenfolge wie die angegebenen. Stellen Sie sicher, dass Ihre Bestellung vom Typ, dann Name, ng-Modell ng-init, Wert ist. das ist es.


0

Hier möchte ich meinen Arbeitscode teilen:

<input type="text" name="someData" ng-model="data" ng-init="data=2" style="display: none;"/>
OR
<input type="hidden" name="someData" ng-model="data" ng-init="data=2"/>
OR
<input type="hidden" name="someData" ng-init="data=2"/>



Sicher! Wenn wir ein verstecktes Feld oder ein Textfeld mit dem Attribut display: none verwenden, kann der Benutzer keinen Wert eingeben. In diesem Fall hilft die Anweisung ng-init, den Wert für das Feld festzulegen. Vielen Dank
J. Middya

in der Post meinte ich Sorry
JSmith
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.