192 votes

AngularJS n'envoie pas la valeur du champ caché

Pour un cas d'utilisation spécifique, je dois soumettre un formulaire unique à l'"ancienne méthode". Autrement dit, j'utilise un formulaire avec action="". La réponse est diffusée en continu, ce qui m'évite de recharger la page. Je suis tout à fait conscient qu'une application AngularJS typique ne soumettrait pas un 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 à partir d'Angular :

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

Veuillez noter que la valeur correcte des données est indiqué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 j'appuie sur "submit", aucune valeur n'est envoyée au serveur. Si je modifie le champ de saisie pour qu'il contienne du "texte", cela fonctionne comme prévu. Je suppose que le champ caché n'est pas réellement rempli, alors que le champ de texte est affiché en raison de la liaison bidirectionnelle.

Avez-vous une idée de la façon dont je peux soumettre un champ caché rempli par AngularJS ?

4 votes

Hmm... et si on tapait du texte, display: none; ? Mais c'est moche. Angular ignore les éléments cachés.

0 votes

Mettez cela comme réponse @tymeJV !

7 votes

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.

290voto

Mickael Points 2178

Vous ne pouvez pas utiliser la double liaison avec un champ caché. La solution consiste à utiliser des parenthèses :

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

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

EDITAR:

Depuis Angular 1.2, vous pouvez utiliser la directive 'ng-value' pour lier une expression à l'attribut valeur d'une entrée. Cette directive doit être utilisée avec les entrées radio ou checkbox mais fonctionne bien avec les entrées cachées.

Voici la solution en utilisant ng-value :

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

Voici un exemple d'utilisation de ng-value avec une entrée cachée : http://jsfiddle.net/6SD9N

0 votes

Génial. Merci beaucoup. J'étais sur le point de cacher le champ de texte, mais maintenant je pense que c'est une excellente solution.

22 votes

Super. Et vous pouvez également utiliser ng-value="modelName" pour le faire sans parenthèses.

2 votes

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

47voto

tymeJV Points 48178

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

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

0 votes

Merci ! J'ai pensé dans le même sens, mais j'ai simplement dû préférer la {{}} solution de Mickael. Solution de Mickael.

1 votes

Solution intelligente / smart

8voto

meffect Points 431

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 votes

Bon point... Je préférerais le faire uniquement dans le contrôleur la prochaine fois.

0 votes

Je suis en train de tomber amoureux de ng-init

0 votes

Nooooon. dans la boucle, il fait beaucoup de problèmes et assigne la dernière valeur à tous les entityId si entityId est un tableau

4voto

Joan JB Points 21

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

et ensuite lier 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 cachée ne déclenche pas d'événement de changement en javascript comme l'a dit yycorman sur este de sorte que la modification de la valeur au moyen d'un plugin jQuery fonctionnera toujours.

Editar J'ai modifié la directive pour appliquer la nouvelle valeur au modèle lorsque l'événement de changement est déclenché, afin qu'elle fonctionne 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());
                });
            });
        }
    };
})

donc quand vous déclenchez $("#yourInputHidden").trigger('change') avec jQuery, il mettra également à jour le modèle lié.

0 votes

Quelqu'un d'autre a-t-il des difficultés à 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, ce qui fait que le $watch n'est pas ajouté.

0 votes

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

0 votes

Il y a un autre problème. jQuery ne déclenche pas d'événement de changement lorsque vous modifiez par programme la valeur d'un champ de saisie caché. Ainsi, si je dis $(hidden_input_elt).val("snoopy"), je dois également ajouter .change() pour que l'événement de changement soit déclenché. Le problème est qu'Angular se plaindra de l'ajout de $scope.apply() parce qu'il est déjà dans un $apply en cours. La solution ici est de supprimer le $scope.$apply dans la fonction de changement ci-dessus et d'appeler simplement ngModel.$setViewValue(...).

2voto

dcalliances Points 931

Nous avons trouvé un comportement étrange à propos de cette valeur cachée () et nous n'arrivons pas à la faire fonctionner.

Après avoir joué un peu, nous avons trouvé que la meilleure façon de procéder est de 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 
}

}])

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X