AngularJS n'envoie pas de valeur de champ masqué


192

Pour un cas d'utilisation spécifique, je dois soumettre un seul formulaire «à l'ancienne». Cela signifie que j'utilise un formulaire avec action = "". La réponse est diffusée, donc je ne recharge pas la page. Je suis tout à fait conscient qu'une application AngularJS typique ne soumettrait pas de formulaire de cette façon, mais jusqu'à présent, je n'ai pas d'autre choix.

Cela dit, j'ai essayé de remplir certains champs cachés d'Angular:

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

Veuillez noter que la valeur correcte des données est affichée.

Le formulaire ressemble à un formulaire standard:

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

Si je clique sur Soumettre, aucune valeur n'est envoyée au serveur. Si je change le champ de saisie pour taper "texte", cela fonctionne comme prévu. Mon hypothèse est que le champ caché n'est pas vraiment rempli, alors que le champ de texte est en fait affiché en raison de la liaison bidirectionnelle.

Des idées sur la façon dont je peux soumettre un champ masqué rempli par AngularJS?


4
Hmm ... que diriez-vous de taper du texte display: none;? C'est moche tho. Angular ignore les éléments cachés.
tymeJV

mettez cela comme réponse @tymeJV!
Jeroen Ingelbrecht

7
J'utilise la syntaxe suivante pour lier une valeur: <input type="hidden" required ng-model="data.userid" ng-init="data.userid=pivot.id" /> . Ce n'est peut-être pas la bonne façon de faire, mais cela fonctionne pour moi.
John P

Réponses:


287

Vous ne pouvez pas utiliser de double liaison avec un champ masqué. La solution est d'utiliser des crochets:

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

EDIT: Voir ce fil sur github: https://github.com/angular/angular.js/pull/2574

ÉDITER:

Depuis Angular 1.2, vous pouvez utiliser la directive 'ng-value' pour lier une expression à l'attribut value de input. Cette directive doit être utilisée avec une radio d'entrée ou une case à cocher mais fonctionne bien avec une entrée masquée.

Voici la solution utilisant ng-value:

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

Voici un violon utilisant ng-value avec une entrée cachée: http://jsfiddle.net/6SD9N


Impressionnant. Merci beaucoup. J'allais presque cacher le champ de texte, mais maintenant je pense que c'est une excellente solution de contournement.
Christian

22
Génial. Et vous pouvez également utiliser ng-value = "modelName" pour le faire sans crochets.
Jonathan

2
C'est vrai, depuis Angular 1.2, vous pouvez utiliser ng-value pour lier une expression à l'attribut value, la réponse est à jour.
Mickael

avez-vous vraiment besoin d'un champ caché lorsque vous utilisez AngularJS? sur ngSubmit, vous frappez un contrôleur, toutes vos données sont complètement visibles pour l'accès, et vous les envoyez via un service $ http.
mtpultz

3
Merci beaucoup. Le fait que ng-model ne puisse pas être utilisé pour une entrée masquée doit être documenté dans AngularJS IMO.
yoonchee

47

Vous pouvez toujours utiliser un type=textet display:none;puisque Angular ignore les éléments masqués. Comme le dit OP, normalement vous ne le feriez pas, mais cela semble être un cas particulier.

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

Merci! Je pensais dans le même sens, mais je devais simplement préférer la {{}} Solution de Mickael.
Christian

1
solution intelligente / intelligente
ImranNaqvi

8

Dans le contrôleur:

$scope.entityId = $routeParams.entityId;

Dans la vue:

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

1
Bon point ... je préfère le faire uniquement dans le contrôleur la prochaine fois
meffect

je tombe amoureux de ng-init
ImranNaqvi

Nooon. en boucle, il fait beaucoup de mal et attribue la dernière valeur à tout entityIdsi entityIdest un tableau
ImranNaqvi

4

J'ai trouvé une belle solution écrite par Mike sur sapiensworks . C'est aussi simple que d'utiliser une directive qui surveille les changements sur votre modèle:

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

puis liez votre entrée:

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

Mais la solution fournie par tymeJV pourrait être meilleure car l'entrée masquée ne déclenche pas l'événement de changement en javascript comme l'a dit yycorman dans cet article, donc lorsque vous changez la valeur via un plugin jQuery, cela fonctionnera toujours.

Edit J'ai modifié la directive pour appliquer une nouvelle valeur au modèle lorsque l'événement de modification est déclenché, il fonctionnera donc comme un texte d'entrée.

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

Ainsi, lorsque vous déclenchez un $("#yourInputHidden").trigger('change')événement avec jQuery, il mettra également à jour le modèle lié.


Quelqu'un d'autre a-t-il du mal à faire fonctionner cette solution? Le problème est que le paramètre ngModel n'est pas défini lorsque la directive est analysée et exécutée, par conséquent, $ watch n'est pas ajouté.
icfantv

D'accord. Il semble que le problème soit que le quatrième paramètre ngModel est un objet, alors que l'exemple référencé à partir du lien de sapiensworks récupère la valeur de chaîne de l'attribut ng-model via attr ['ngModel'], puis la transmet à la montre. Je peux confirmer que cette modification résout le problème de la montre.
icfantv

Il y a un autre problème ici. jQuery ne déclenche pas d'événement de modification lorsque vous modifiez par programme la valeur d'un champ d'entrée masqué. Donc, si je dis $ (hidden_input_elt) .val ("snoopy"), je dois également ajouter .change () pour déclencher l'événement de changement. Le problème avec ceci est qu'Angular se plaindra du $ scope.apply () ci-dessus car il est déjà dans un $ apply est déjà en cours. La solution ici est de supprimer $ scope. $ Apply dans la fonction de changement ci-dessus et d'appeler simplement ngModel. $ SetViewValue (...).
icfantv

2

Nous avons trouvé un comportement étrange à propos de cette valeur cachée () et nous ne pouvons pas le faire fonctionner.

Après avoir joué, nous avons trouvé que le meilleur moyen consiste simplement à définir la valeur dans le contrôleur lui-même après la portée du formulaire.

.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

J'ai réalisé cela via -

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

1

mettre à jour la réponse de @tymeJV, par exemple:

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

0

J'ai eu le même problème, j'ai vraiment besoin d'envoyer une clé de mon jsp au script java, cela passe environ 4h ou plus de ma journée à le résoudre.

J'inclus cette balise sur mon JavaScript / JSP:

 $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}. -->

Le résultat était: Portfólio 1 criado com sucesso! ID = 3.

Meilleures salutations


0

Juste au cas où quelqu'un aurait encore du mal avec cela, j'ai eu un problème similaire en essayant de garder une trace de la session utilisateur / de l'ID utilisateur sur un formulaire multipage

J'ai corrigé cela en ajoutant

.when ("/ q2 /: uid" dans le routage:

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

Et ajouté ceci en tant que champ caché pour passer des paramètres entre les pages de formulaire Web

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

Je suis nouveau sur Angular, donc je ne suis pas sûr que ce soit la meilleure solution possible, mais cela semble fonctionner correctement pour moi maintenant


0

Attribuez directement la valeur au modèle dans l' data-ng-valueattribut. Puisque l'interpréteur angulaire ne reconnaît pas les champs cachés dans le cadre de ngModel.

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

0

J'utilise un javascript classique pour définir la valeur sur une entrée masquée

$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

Le code ci-dessous fonctionnera pour cet IFF dans le même ordre que celui mentionné, assurez-vous que votre commande est de type puis de nom, ng-model ng-init, valeur. c'est tout.


0

Ici, je voudrais partager mon code de travail:

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


Pourriez-vous plus d'explications s'il vous plaît
JSmith

Sûr! Lorsque nous utilisons un champ masqué ou un champ de texte avec un attribut display: none, l'utilisateur ne peut pas saisir de valeur. Dans ce cas, la directive ng-init aide à définir la valeur du champ. Merci
J. Middya

dans le post Je voulais dire Désolé
JSmith
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.