Question

So, I have this code Fiddle

<div ng-app="testApp">
<div ng-controller="MainCtrl">
    <form>
        <p>
            <select ng-model="selectedItem" ng-options="i.name for i in items"></select>
        </p>
        <p ng-show="selectedItem.subItems">
            <select ng-model="selectedSubItem" ng-options="i.name for i in selectedItem.subItems"></select>
        </p>

        <p ng-show="selectedSubItem.subItems">
            <select ng-model="selectedSubSubItem" ng-options="i.name for i in selectedSubItem.subItems"></select>
        </p>

        <input type="hidden" name="selection" value="????">

        <input type="submit" value="submit">
    </form>

</div>

And in that code I only show the next dropdown if the selected item has a child array. Now, I want to populate the value of the hidden field with the last selected value of that dropdown chain using Angular.js.

In another word, if the user chooses an option in the last dropdown that appear, I want that hidden field at the end to have that value to be submitted with the form.

How can I do that?

Was it helpful?

Solution 2

This may do, if the length of the chain is fixed:

<input type="hidden" name="selection"
    value="{{ (selectedSubSubItem || selectedSubItem || selectedItem).name }}"/>

To solve the problem with going backwards to the chain, a simple solution is to use ng-change and nullify all the next values, i.e.:

<select ng-model="selectedItem" ng-options="i.name for i in items"
    ng-change="selectedSubItem=null;selectedSubSubItem=null"></select>

See forked fiddle: http://jsfiddle.net/zH77p/1/


Alternatively to the ng-change, you can use watches in the scope; the advantage is that the watches only need to know their immediate child:

$scope.$watch("selectedItem", function(newval, oldval) {
    if( newval !== oldval ) $scope.selectedSubItem = null;
});
$scope.$watch("selectedSubItem", function(newval, oldval) {
    if( newval !== oldval ) $scope.selectedSubSubItem = null;
});

OTHER TIPS

You can use:

<input type="hidden" name="selection" value="{{selectedSubSubItem.name}}">

The two-way binding will update the value of the hidden input once the value of the respective select gets changed.

If you want to get it dynamically based on the last selected:

<input type="hidden" name="selection" value="{{selectedSubSubItem.name || selectedSubItem.name || selectedItem.name}}">

If you want to be able to go back in the chain this will help. But I strongly recommend to move this logic to the controller:

<input type="hidden" name="selection" value="{{(selectedSubItem.subItems ? selectedSubSubItem.name : false) || (selectedItem.subItems ? selectedSubItem.name : false) || selectedItem.name}}">

Since you are interested in this type of "chained selection", you need to use some more complex logic. Here's the fiddle: http://jsfiddle.net/2Az4P/3/ I used ng-value, but you can leave your value and set it to

value="{{choiceValue()}}

which would have the same effect. What I did was to make the answers in an array (selectedItem = []) and then populate it as I go along (notice the ng-model of each selection).

On each selection, the value updates accordingly using the function choiceValue() which updates the ng-value accordingly.

This way, you can add as many selections to the chain, and just update their number (actually, you could use ng-repeat for this, and use the $index to automatically create more choice levels).

It's a bit more work, but you can see the basics here: http://jsfiddle.net/brendanowen/uXbn6/8/

It all depends how complex/automated you need to do this :)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top