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?

chrześcijanin
źródło
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

Mickael
źródło
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;"/>
tymeJV
źródło
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" />
skuteczny
źródło
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.

Joan JB
źródło
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 
}

}])
dcpartners
źródło
1

Osiągnąłem to przez -

 <p style="display:none">{{user.role="store_user"}}</p>
Vivex
źródło
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>
Albert.Qing
źródło
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

LeoJava
źródło
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

macieku
źródło
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"/>
Nikhil.Hmath
źródło
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;
    }
}
Ivan Kuznietsov
źródło
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.

Pawan Parashar
źródło
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"/>

J. Middya
źródło
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