ChatGPT解决这个技术问题 Extra ChatGPT

AngularJS does not send hidden field value

For a specific use case I have to submit a single form the "old way". Means, I use a form with action="". The response is streamed, so I am not reloading the page. I am completely aware that a typical AngularJS app would not submit a form that way, but so far I have no other choice.

That said, i tried to populate some hidden fields from Angular:

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

Please note, the correct value in data is shown.

The form looks like a standard form:

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

If I hit submit, no value is sent to the server. If I change the input field to type "text" it works as expected. My assumption is the hidden field is not really populated, while the text field actually is shown due two-way-binding.

Any ideas how I can submit a hidden field populated by AngularJS?

Hmm... how about type text, display: none;? It's ugly tho. Angular ignores hidden elements.
put that as the answer @tymeJV!
I use the following syntax to bind a value: <input type="hidden" required ng-model="data.userid" ng-init="data.userid=pivot.id" /> . This might not be the proper way of doing but it works for me.

M
Mickael

You cannot use double binding with hidden field. The solution is to use brackets :

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

EDIT : See this thread on github : https://github.com/angular/angular.js/pull/2574

EDIT:

Since Angular 1.2, you can use 'ng-value' directive to bind an expression to the value attribute of input. This directive should be used with input radio or checkbox but works well with hidden input.

Here is the solution using ng-value:

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

Here is a fiddle using ng-value with an hidden input: http://jsfiddle.net/6SD9N


Awesome. Thanks a lot. I was almost going with hiding the textfield, but now i feel this is great workaround.
Great. And also you can use ng-value="modelName" to do it without brackets.
That's right, since Angular 1.2, you can use ng-value to bind an expression to the value attribute, the answer is up to date.
do you really need a hidden field anymore when you use AngularJS? on ngSubmit you hit a controller all your data is completely visible for access, and you send it all via some $http service.
Thanks a lot. The fact that ng-model cannot be used for hidden input should be documented in AngularJS IMO.
t
tymeJV

You can always use a type=text and display:none; since Angular ignores hidden elements. As OP says, normally you wouldn't do this, but this seems like a special case.

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

Thanks! I thought in the same direction, but I simply had to prefer the {{}} Solution from Mickael.
clever / smart solution
N
Northstrider

In the controller:

$scope.entityId = $routeParams.entityId;

In the view:

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

Good point... I would rather do this only in the controller next time
i'm falling in love with ng-init
Nooo . in loop it makes much trouble and assigns last value to all entityId if entityId is an array
C
Community

I've found a nice solution written by Mike on sapiensworks. It is as simple as using a directive that watches for changes on your model:

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

and then bind your input:

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

But the solution provided by tymeJV could be better as input hidden doesn't fire change event in javascript as yycorman told on this post, so when changing the value through a jQuery plugin will still work.

Edit I've changed the directive to apply the a new value back to the model when change event is triggered, so it will work as an input text.

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

so when you trigger $("#yourInputHidden").trigger('change') event with jQuery, it will update the binded model as well.


Is anyone else having trouble getting this solution to work? The issue is that the ngModel parameter is undefined when the directive is parsed and executed, thus, the $watch isn't added.
Ok. It appears the issue is that the fourth parameter ngModel is an object, whereas the example referenced from the link at sapiensworks retrieves the string value of the ng-model attribute via attr['ngModel'] and then passes that in to the watch. I can confirm that making this change fixes the watch issue.
There's another issue here. jQuery does not fire a change event when you programmatically change the value of a hidden input field. So if I say $(hidden_input_elt).val("snoopy") I have to also add .change() to cause the change event to be fired. The problem with this is that Angular will complain about the above $scope.apply() because it's already in an $apply is already in progress. The solution here is to remove the $scope.$apply in the change function above and just call ngModel.$setViewValue(...).
d
dcpartners

Found a strange behaviour about this hidden value () and we can't make it to work.

After playing around we found the best way is just defined the value in controller itself after the form scope.

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

}])

v
vivex

I achieved this via -

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

A
Albert.Qing

update @tymeJV 's answer eg:

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

L
LeoJava

I had facing the same problem, I really need to send a key from my jsp to java script, It spend around 4h or more of my day to solve it.

I include this tag on my 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; };

{{inforMessage}}

The result was: Portfólio 1 criado com sucesso! ID=3.

Best Regards


m
macieku

Just in case someone still struggles with this, I had similar problem when trying to keep track of user session/userid on multipage form

Ive fixed that by adding

.when("/q2/:uid" in the routing:

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

And added this as a hidden field to pass params between webform pages

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

Im new to Angular so not sure its the best possible solution but it seems to work ok for me now


g
gofr1

Directly assign the value to model in data-ng-value attribute. Since Angular interpreter doesn't recognize hidden fields as part of ngModel.

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

I
Ivan Kuznietsov

I use a classical javascript to set value to hidden input

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

P
Pawan Parashar

Below Code will work for this IFF it in the same order as its mentionened make sure you order is type then name, ng-model ng-init, value. thats It.


J
J. Middya

Here I would like to share my working code :

OR OR


could you a more explanations please
Sure! When we use hidden field or a text field with display:none attribute, user is not able to input value. In that case ng-init directive helps to set the value for the field. Thanks
in the post I meant Sorry