How to handle two inputs which depend on each other? - reactjs

Let's say that I have to <select> lists:
<select valueLink={this.linkState('parent')}>...</select>
<select valueLink={this.linkState('child')}>...</select>
Child select depends on parent select (when parent is selected then child is filled with new options and its value is set to first option by default.
The problem is that in order to "reset" child select I would have to set component state in response to state-change event, which is highly discouraged AFAIK. So how to handle this situation?

If I understand your issue correctly, this may help.
JSFIDDLE
By changing what options the select has we automatically reset it when we change the first select. I've also made the second select completely dependent on the first select's state.
<select valueLink={this.linkState('select')}>
{this.renderOptions(Object.keys(this.selectOptions))}
</select>
<select>
{this.renderOptions(this.selectOptions[this.state.select])}
</select>
let me know if I misunderstood your issue.
Update / EDIT:
I think I understand your issue a bit more. In this case you have a complicated relationship with your two inputs, and can't rely on the 1:1 relationship that this.linkState() gives you.
In this case I added a custom onChange method to the first select and set the value and initial value of the second selection from that. Since the second selection isn't doing anything fancy we can use linkState on it just fine.
UPDATED FIDDLE
<select onChange={this.handleMainSelectChange}>
{this.renderOptions(Object.keys(this.selectOptions))}
</select>
<select valueLink={this.linkState('secondSelection')}>
{this.renderOptions(this.selectOptions[this.state.mainSelection])}
</select>
And the click handler
handleMainSelectChange: function (event) {
var value = event.target.value;
this.setState({
mainSelection: value,
secondSelection: this.selectOptions[value][0]
});

Related

selected value in one dropdown should not appear in another dropdowns. how to remove selected element?

Sorry for asking this question again. but I'm new to angularjs. my que is...
I have five drop downs which are loading from json using angular js(ng-option). now I need that if user selecting value in one drop down that same value should not appear in another four dropdowns.
I really want solution. I search a lot and practice more and more but. Couldn't find any solution. Plz plz plz help me.
I'm not sure if I've got your problem right, but I would try to create an array, let's say $scope.selectedOptions. And then on select push the value to this array. After that you can filter the options in other dropdowns with lodash for example.
here is the solution that you can apply in easy way.
one model you sending to other select.
<select ng-model="countryList"
data-ng-options="countryList for countryList in countryListArray" ng-change="getStates(countryList)" >
<option value="" disabled selected>-- Choose Country--</option>
<select ng-disabled="!countryList" ng-model="stateList"
data-ng-options="stateList for stateList in stateListArray" ng-change="getCities(stateList)" >
<option value="" disabled selected>-- Choose State --</option>
</select>
you need to add below code in your dropdown elements so as to avoid recursive calls to all three of your dropdowns during change in ng-model values.
ng-model-options="{ updateOn: 'change', debounce: { change: 0 } }"
Also there is a function which updates data object of your $scope.records array. Please take a look at this fiddle. I think this is what the specific thing is which you wanted.

Roll back ngOptions select to unselected state

ngOpions creates a blank option like option html below if the model value doesn't match any of the option values:
<option value="?" selected="selected"></option>
After a selection is made, AngularJS removes this first empty option html from the select html.
I have a use case where I want to roll back the state of the html select to the unselected option which AngularJS removed. I tried ngModel methods like $setPristine(), $rollbackViewValue(), and $setUntouched(). But none of these mothods puts the state of the select back to the initial state with the empty option.
Is it possible to truely roll back an AngularJS select element to have the empty option after a selection is made?
The code for ngOptions (line 473 in ngOptions.js ) suggests that only single-select can get it, and that the writeValue function (called when the ngModel changes) has to be invoked with a null value (not undefined, as === is used.)
So you can try setting your model variable to null.
If that doesn't work, I expect you may be out of luck as far as proper solutions go, and might need to re-render the whole directive. You can create a pretty simple directive to do that, similar to what's suggested in this answer: https://stackoverflow.com/a/22133080/624590

Dynamic Select List Default Selected Item - Angular JS

I have the code listed below which works fine, however when i attempt to add ng-model and related ng-change to the select, an empty option is added. I understanding why, it is because on init the selectedOption for ng-model is empty.
What I want to do is set a default value so when I can use ng-change to set options IsSelected value to true when user selects it. I'm just not sure how to go about this, I have no issues doing this when I'm working with a static generated select list, but for some reason I can't figure it out for this dynamic generated list.
Any input is appreciated!
<div ng-repeat="optionType in productDetailModel.OptionTypes">
<select name="{{optionType.OptionTypeName}}">
<option ng-repeat="option in optionType.Options"
value="{{option.OptionValue}}">{{option.OptionValue}}
</option>
</select>
</div>
Here's plunkr I mocked to give a basic idea of what I have in mind: http://plnkr.co/edit/xBDfc0XzDwsF0mBiFZOv?p=preview
The initial option is blank because the model is initially undefined.
As tymeJV said, initializing your scope inside of your .js will define a default value that will be shown as selected initially.
$scope.modelName = $scope.optionType.Options[0];
It might be helpful to use ng-options instead of ng-repeat. One reason why it might be beneficial is that ng-options does not create a child scope (unlike ng-repeat). This could help simplify linking to your model and avoid confusion.
<select name="{{optionType.OptionTypeName}}" ng-model="modelName" ng-options="option for option in optionType.Options">
</select>
This article covers the basics of ng-options as well as discusses why it would be used as opposed to ng-repeat.
Hope this helps.
Use ng-options when using a select!
<select name="{{optionType.OptionTypeName}}" ng-model="someModel" ng-options="option as option for option in optionType.Options>
</select>
And then set the ngModel to the default option you want selected:
$scope.someModel = $scope.optionType.Options[0]
There is one directive of select element is ng-init but it call once while first time rendering, but if you change the options dynamically then it will not call again. So for that you need to set the model field with value in scope just below of your new option population logic.
$scope.modelName = $scope.Options[0]; // if array
$scope.modelName = $scope.Options[key]; // if Json Object

Can't get Angular select to update with selected value

I'm using selects to allow a user to switch between events and years. Each change will pull appropriate data from the server, return and update the page. However, the select box goes from the selected value to an empty value. I've looked at numerous solutions and they aren't working.
<select
ng-model="eventName"
ng-options="item.value for item in eventOptions track by item.value"
ng-change="changeEvent(eventName.value)">
</select>
This is the changeEvent function:
$scope.changeEvent = function(eventName){
$scope.eventName = eventName; //wrongly assumed this would update the selected value
$scope.getData($scope.eventName,$scope.eventYear); //this returns the json - correct
$scope.updateSelected(); //meant to update the select field value on the page - fails
};
$scope.eventName or $scope.eventYear values will properly update on a change, but has no effect on the page. The selects just empty of a selected value.
UPDATED (with corrected code)
I wanted to post the changes I made more clearly than the comment allows.
I removed the object param "value" from the options and the argument from the function call (eventName.value).
<select
ng-model="eventName"
ng-options="item for item in eventOptions track by item"
ng-change="changeEvent()">
</select>
And the changeEvent function gets simplified to:
$scope.changeEvent = function(){
$scope.getData($scope.eventName,$scope.eventYear);
};
It all works as expected! Thanks to all, especially Delta who got me looking at it the right way.
So, your event name variable is set to be item. not item.value so instead of passing in changeEvent(eventName.value) try passing in changeEvent(eventName). either way the value you are passing into your method doesnt match the value of your model's variable
item.value for item in eventOptions track by item.value
so for this statement, you are saying make my options ng-model=item but make their value=item.value so they show what you want them to show but still have all the information you need from each one.
Upon further inspection is looks like you dont need:
$scope.eventName = eventName;
$scope.updateSelected();
Angular should be updating your eventName for you, you just need to call the change method.
I'm not sure you need:
ng-change="changeEvent(eventName.value)"
if you use ng-options the model will be updated in the scope automatically on selection. You could watch the value in the controller if you want to do other stuff when it changes:
$scope.$watch('eventName', function() {
//do stuff
});

How can I detect when a USER changes the value in a select drop down using AngularJS?

I have the following:
<select data-ng-model="selectedTestAccount" data-ng-options="item.Id as item.Name for item in testAccounts">
<option value="">Select Account</option>
</select>
It was suggested to me that I could watch for the value of this select to change with the following:
$scope.$watch('testAccounts', function(){
/* get updated values and update other select "model" on success*/
alert("hello");
});
But this does not seem to work. For one thing it gives an alert as soon as the select appears on the screen and before the user has selected anything. Also am I correct in saying that I should be watching for a change in selectedTestAccount? Finally one more question. How can I show the value of selectedTestAccount in an alert box?
As said, you can get it as the first argument, no need to get it from scope. Use
$scope.$watch('selectedTestAccount', function(newValue){
alert(newValue);
});
Beware that you always get a undefined as the first change for a $watch.
What about putting an "ng-change" to your select?
In your example it would be something like this:
<select data-ng-model="selectedTestAccount" ng-change="updateSelectedAccount(selectedTestAccount)" data-ng-options="item.Id as item.Name for item in testAccounts"></select>
And then in your controller
$scope.updateSelectedAccount = function (selectedTestAccount) {
console.log(selectedTestAccount);
}
P.S. Sorry, just noticed how old this question is :) Hope this might help somebody in the future.

Resources