AngularJS nie wysyła wartości ukrytego pola


192

W przypadku konkretnego zastosowania muszę przesłać pojedynczy formularz „starą drogą”. Znaczy, używam formularza z działaniem = "". Odpowiedź jest przesyłana strumieniowo, więc nie ładuję strony ponownie. Jestem w pełni świadomy, że typowa aplikacja AngularJS nie przesyła formularza w ten sposób, ale jak dotąd nie mam innego wyboru.

To powiedziawszy, próbowałem wypełnić niektóre ukryte pola z Angulara:

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

Uwaga: wyświetlana jest poprawna wartość w danych.

Formularz wygląda jak standardowy formularz:

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

Po naciśnięciu przycisku Prześlij żadna wartość nie zostanie wysłana na serwer. Jeśli zmienię pole wprowadzania na „tekst”, będzie działać zgodnie z oczekiwaniami. Moje założenie jest takie, że ukryte pole nie jest tak naprawdę wypełnione, podczas gdy pole tekstowe jest faktycznie wyświetlane ze względu na dwukierunkowe wiązanie.

Jakieś pomysły, jak mogę przesłać ukryte pole wypełnione przez AngularJS?


4
Hmm ... co powiesz na tekst display: none;? To brzydkie. Kątowe ignoruje ukryte elementy.
tymeJV

umieść to jako odpowiedź @tymeJV!
Jeroen Ingelbrecht

7
I użyj następującej składni, aby powiązać wartości: <input type="hidden" required ng-model="data.userid" ng-init="data.userid=pivot.id" /> . To może nie być właściwy sposób, ale działa dla mnie.
John P

Odpowiedzi:


287

Nie można używać podwójnego wiązania z ukrytym polem. Rozwiązaniem jest użycie nawiasów:

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

EDYCJA: Zobacz ten wątek na github: https://github.com/angular/angular.js/pull/2574

EDYTOWAĆ:

Od wersji Angular 1.2 możesz użyć dyrektywy „ng-value”, aby powiązać wyrażenie z atrybutem wartości wejścia. Niniejsza dyrektywa powinna być używana z wejściowym radiem lub polem wyboru, ale działa dobrze z ukrytym wejściem.

Oto rozwiązanie wykorzystujące wartość ng:

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

Oto skrzypce używające wartości ng z ukrytym wejściem: http://jsfiddle.net/6SD9N


Niesamowite. Wielkie dzięki. Niemal chciałem ukryć pole tekstowe, ale teraz uważam, że to świetne obejście.
Christian

22
Wspaniały. A także możesz użyć ng-value = "modelName", aby zrobić to bez nawiasów.
Jonathan

2
Zgadza się, ponieważ od Angulara 1.2 możesz użyć ng-value do powiązania wyrażenia z atrybutem wartości, odpowiedź jest aktualna.
Mickael

czy naprawdę potrzebujesz ukrytego pola już podczas korzystania z AngularJS? na ngSubmit trafisz do kontrolera, wszystkie twoje dane są całkowicie widoczne dla dostępu i wysyłasz je za pośrednictwem jakiejś usługi $ http.
mtpultz

3
Wielkie dzięki. Fakt, że model ng nie może być używany do ukrytych danych wejściowych, powinien zostać udokumentowany w AngularJS IMO.
yoonchee

47

Zawsze możesz użyć type=text a, display:none;ponieważ Angular ignoruje ukryte elementy. Jak mówi OP, normalnie byś tego nie zrobił, ale wydaje się to szczególnym przypadkiem.

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

Dzięki! Myślałem w tym samym kierunku, ale po prostu musiałem preferować rozwiązanie {{}} firmy Mickael.
Christian

1
sprytne / inteligentne rozwiązanie
ImranNaqvi

8

W kontrolerze:

$scope.entityId = $routeParams.entityId;

W widoku:

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

1
Dobra uwaga ... Wolę to zrobić tylko następnym razem w kontrolerze
skuteczny

zakochuję się w ng-init
ImranNaqvi

Nieee w pętli sprawia wiele problemów i przypisuje ostatnią wartość do wszystkich, entityIdjeśli entityIdjest tablicą
ImranNaqvi

4

Znalazłem fajne rozwiązanie napisane przez Mike'a w sapiensworks . Jest to tak proste, jak użycie dyrektywy, która obserwuje zmiany w twoim modelu:

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

a następnie powiąż swoje dane wejściowe:

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

Ale rozwiązanie dostarczone przez tymeJV mogłoby być lepsze, ponieważ wejście ukryte nie uruchamia zdarzenia zmiany w javascript, jak powiedział yycorman w tym poście, więc przy zmianie wartości za pomocą wtyczki jQuery nadal będzie działać.

Edytuj Zmieniłem dyrektywę, aby zastosować nową wartość z powrotem do modelu, gdy zostanie wywołane zdarzenie zmiany, więc będzie działać jako tekst wejściowy.

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

więc kiedy wywołasz $("#yourInputHidden").trigger('change')zdarzenie za pomocą jQuery, zaktualizuje on również powiązany model.


Czy ktoś ma problem z uruchomieniem tego rozwiązania? Problem polega na tym, że parametr ngModel jest niezdefiniowany, gdy dyrektywa jest analizowana i wykonywana, dlatego $ watch nie jest dodawany.
icfantv

Dobrze. Wydaje się, że problemem jest to, że czwarty parametr ngModel jest obiektem, podczas gdy przykład, do którego odwołuje się link w sapiensworks, pobiera wartość ciągu atrybutu ng-model przez attr ['ngModel'], a następnie przekazuje go do zegarka. Mogę potwierdzić, że ta zmiana rozwiązuje problem z zegarkiem.
icfantv

Jest tu inny problem. jQuery nie uruchamia zdarzenia zmiany, gdy programowo zmienisz wartość ukrytego pola wejściowego. Jeśli więc powiem $ (hidden_input_elt) .val („snoopy”), muszę również dodać .change (), aby wywołać zdarzenie zmiany. Problem polega na tym, że Angular będzie narzekał na powyższy $ scope.apply (), ponieważ jest już w $ Apply, już trwa. Rozwiązaniem jest usunięcie zakresu $. $ Zastosuj w powyższej funkcji zmiany i po prostu wywołaj ngModel. $ SetViewValue (...).
icfantv

2

Znaleźliśmy dziwne zachowanie dotyczące tej ukrytej wartości () i nie możemy jej uruchomić.

Po zabawie okazało się, że najlepszym sposobem jest zdefiniowanie wartości w samym kontrolerze po zakresie formularza.

.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

Osiągnąłem to przez -

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

1

zaktualizuj odpowiedź @tymeJV, np .:

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

0

Miałem do czynienia z tym samym problemem, naprawdę muszę wysłać klucz z mojego pliku JSP do skryptu Java, aby rozwiązać problem, spędzam około 4 godzin lub dłużej.

Dołączam ten tag do mojego 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}. -->

Rezultat: Portfolio 1 criado com sucesso! ID = 3.

Z poważaniem


0

Na wypadek, gdyby ktoś nadal miał z tym problem, miałem podobny problem podczas próby śledzenia sesji użytkownika / identyfikatora użytkownika na formularzu wielostronicowym

Naprawiłem to, dodając

.when („/ q2 /: uid” w routingu:

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

I dodał to jako ukryte pole do przekazywania parametrów między stronami formularza internetowego

<< input type = "ukryty" wymagany ng-model = "formData.userid" ng-init = "formData.userid = uid" />

Jestem nowy w Angular, więc nie jestem pewien, czy jest to najlepsze możliwe rozwiązanie, ale wydaje mi się, że teraz działa dobrze


0

Bezpośrednio przypisz wartość do modelu w data-ng-valueatrybucie. Ponieważ interpreter kątowy nie rozpoznaje ukrytych pól jako części ngModel.

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

0

Używam klasycznego javascript do ustawiania wartości ukrytych danych wejściowych

$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

Poniższy kod będzie działał dla tego IFF w tej samej kolejności, w jakiej wspomniano, upewnij się, że zamawiasz to type, a następnie name, ng-model ng-init, value. Otóż ​​to.


0

Tutaj chciałbym udostępnić mój działający kod:

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


proszę o więcej wyjaśnień
JSmith

Pewnie! Kiedy używamy ukrytego pola lub pola tekstowego z atrybutem display: none, użytkownik nie może wprowadzić wartości. W takim przypadku dyrektywa ng-init pomaga ustawić wartość dla pola. Dzięki
J. Middya,

w poście miałem na myśli przepraszam
JSmith
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.