AngularJS não envia valor de campo oculto

192

Para um caso de uso específico, tenho que enviar um único formulário da "maneira antiga". Significa, eu uso um formulário com action = "". A resposta é transmitida, por isso não estou recarregando a página. Estou perfeitamente ciente de que um aplicativo AngularJS típico não enviaria um formulário dessa maneira, mas até agora não tenho outra opção.

Dito isto, tentei preencher alguns campos ocultos do Angular:

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

Observe que o valor correto nos dados é mostrado.

O formulário se parece com um formulário padrão:

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

Se eu clicar em enviar, nenhum valor será enviado ao servidor. Se eu alterar o campo de entrada para digitar "texto", ele funcionará conforme o esperado. Minha suposição é que o campo oculto não é realmente preenchido, enquanto o campo de texto é realmente mostrado devido à ligação bidirecional.

Alguma idéia de como posso enviar um campo oculto preenchido pelo AngularJS?

cristão
fonte
4
Hmm ... que tal digitar texto display: none;? É feio. Angular ignora elementos ocultos.
tymeJV
coloque isso como a resposta @tymeJV!
Jeroen Ingelbrecht
7
Eu uso a seguinte sintaxe para vincular um valor: <input type="hidden" required ng-model="data.userid" ng-init="data.userid=pivot.id" /> . Esta pode não ser a maneira correta de fazer, mas funciona para mim.
John P

Respostas:

287

Você não pode usar ligação dupla com campo oculto. A solução é usar colchetes:

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

Edição: Veja este tópico no github: https://github.com/angular/angular.js/pull/2574

EDITAR:

Desde o Angular 1.2, você pode usar a diretiva 'ng-value' para vincular uma expressão ao atributo value da entrada. Esta diretiva deve ser usada com entrada de rádio ou caixa de seleção, mas funciona bem com entrada oculta.

Aqui está a solução usando o valor ng:

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

Aqui está um violino usando ng-value com uma entrada oculta: http://jsfiddle.net/6SD9N

Mickael
fonte
Impressionante. Muito obrigado. Eu estava quase escondendo o campo de texto, mas agora acho que isso é uma ótima solução.
Christian
22
Ótimo. E também você pode usar ng-value = "modelName" para fazê-lo sem colchetes.
12134 Jonathan
2
Isso mesmo, desde o Angular 1.2, você pode usar o valor-ng para vincular uma expressão ao atributo value, a resposta está atualizada.
Mickael
você realmente precisa de um campo oculto ao usar o AngularJS? no ngSubmit, você acessa um controlador, todos os seus dados ficam completamente visíveis para acesso e envia tudo por meio de algum serviço $ http.
mtpultz
3
Muito obrigado. O fato de o ng-model não poder ser usado para entrada oculta deve ser documentado no AngularJS IMO.
yoonchee
47

Você sempre pode usar um type=texte display:none;desde ignora angular elementos ocultos. Como o OP diz, normalmente você não faria isso, mas esse parece ser um caso especial.

<input type="text" name="someData" ng-model="data" style="display: none;"/>
tymeJV
fonte
Obrigado! Pensei na mesma direção, mas simplesmente tive que preferir a solução {{}} da Mickael.
Christian
1
solução inteligente / inteligente
ImranNaqvi 2/16/16
8

No controlador:

$scope.entityId = $routeParams.entityId;

Na visualização:

<input type="hidden" name="entityId" ng-model="entity.entityId" ng-init="entity.entityId = entityId" />
meffect
fonte
1
Bom ponto ... Eu preferiria fazer isso apenas no controlador próxima vez
meffect
eu estou caindo no amor com ng-init
ImranNaqvi
Nããão. em malha faz muita dificuldade e atribui último valor a todos entityId, se entityIdé um array
ImranNaqvi
4

Encontrei uma boa solução escrita por Mike no sapiensworks . É tão simples quanto usar uma diretiva que observe as alterações no seu modelo:

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

e depois vincule sua entrada:

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

Mas a solução fornecida pelo tymeJV poderia ser melhor, pois a entrada oculta não dispara evento de alteração no javascript, como yycorman disse nesta publicação, portanto, ao alterar o valor através de um plugin do jQuery, ainda funcionará.

Edit Alterei a diretiva para aplicar um novo valor ao modelo quando o evento change for acionado, para que funcione como um texto de entrada.

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

portanto, quando você dispara um $("#yourInputHidden").trigger('change')evento com o jQuery, ele também atualiza o modelo vinculado.

Joan JB
fonte
Alguém mais está tendo problemas para fazer com que esta solução funcione? O problema é que o parâmetro ngModel é indefinido quando a diretiva é analisada e executada, portanto, o $ watch não é adicionado.
icfantv
Está bem. Parece que o problema é que o quarto parâmetro ngModel é um objeto, enquanto o exemplo referenciado no link no sapiensworks recupera o valor da string do atributo ng-model via attr ['ngModel'] e o passa para o relógio. Posso confirmar que essa alteração corrige o problema do relógio.
icfantv
Há outra questão aqui. O jQuery não dispara um evento de alteração quando você altera programaticamente o valor de um campo de entrada oculto. Portanto, se eu disser $ (hidden_input_elt) .val ("snoopy"), também tenho que adicionar .change () para fazer com que o evento de mudança seja acionado. O problema é que o Angular reclamará do $ scope.apply () acima, porque ele já está em um $ apply e já está em andamento. A solução aqui é remover o $ scope. $ Apply na função de mudança acima e apenas chamar ngModel. $ SetViewValue (...).
icfantv
2

Encontramos um comportamento estranho sobre esse valor oculto () e não podemos fazê-lo funcionar.

Depois de brincar, descobrimos que a melhor maneira é apenas definir o valor no próprio controlador após o escopo do formulário.

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

}])
dcpartners
fonte
1

Eu consegui isso via -

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

atualize a resposta de @tymeJV, por exemplo:

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

Eu estava enfrentando o mesmo problema, eu realmente preciso enviar uma chave do meu jsp para o script java, ele passa cerca de 4h ou mais do meu dia para resolvê-lo.

Eu incluo essa tag no meu 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}. -->

O resultado foi: Portfólio 1 criado com sucesso! ID = 3.

Cumprimentos

LeoJava
fonte
0

Caso alguém ainda lute com isso, tive um problema semelhante ao tentar acompanhar a sessão do usuário / ID do usuário no formulário de várias páginas

Eu consertei isso adicionando

.when ("/ q2 /: uid" no roteamento:

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

E adicionou isso como um campo oculto para passar parâmetros entre as páginas do formulário da web

<< tipo de entrada = "oculto" necessário ng-model = "formData.userid" ng-init = "formData.userid = uid" />

Sou novo no Angular, então não tenho certeza que é a melhor solução possível, mas parece funcionar bem para mim agora

macieku
fonte
0

Atribua diretamente o valor ao modelo no data-ng-valueatributo Como o intérprete Angular não reconhece campos ocultos como parte do ngModel.

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

Eu uso um javascript clássico para definir valor para entrada oculta

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

Abaixo, o Code funcionará para este IFF na mesma ordem em que é mencionado. é isso aí.

Pawan Parashar
fonte
0

Aqui eu gostaria de compartilhar meu código de trabalho:

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

J. Middya
fonte
você poderia um mais explicações agradar
JSmith
Certo! Quando usamos um campo oculto ou um campo de texto com display: none, o usuário não pode inserir valor. Nesse caso, a diretiva ng-init ajuda a definir o valor do campo. Obrigado
J. Middya 08/09/18
no post eu quis dizer Desculpe
JSmith 8/08