AngularJS Multiple Select not showing preselected options - angularjs

I have been most part of the morning working on a solution for when I need to assign several values to an entity on my form.
So, the idea is I have an Entity called QualityData and this entity can have different MechanismIdentifiers.
Best solution I thought of, use a multiple select.
All works fine combining both these solutions:
AngularJS selecting multiple options
Get value when selected ng-option changes
I can access the array of selected options, assign it to my entity, etc... But I have a "minor" fallback, which is that I can't get the preselected options (the ones that would come from the server when loading data for editing) to be highlighted in the select field when using a dynamic approach such as <option ng-repeat> or ng-options, it will only work when hardcoding the options. Another bug is that if I wish to add more values than those that are in the preselected array, it will erase all values present in it when using a dynamic approach, working fine when harcoding.
The markup:
<select multiple ng-change="showAlert(selectedValues)" ng-model="selectedValues">
<!--ng-options="resDatasIdOfMechanism as resDatasIdOfMechanism.name for resDatasIdOfMechanism in resDatasIdOfMechanisms track by resDatasIdOfMechanism.id" value="resDatasIdOfMechanism.id">-->
<option value="1">{{resDatasIdOfMechanisms[0].name}}</option>
<option value="2">{{resDatasIdOfMechanisms[1].name}}</option>
<option value="3">{{resDatasIdOfMechanisms[2].name}}</option>
</select>
If I try to use the line that is commented, it's when the marked option will not work
The controller:
$scope.selectedAlready = [{id:1, name:"Based on Antibiogram"}];
$scope.selectedMechanisms=[];
$scope.resDatasIdOfMechanisms = [{id:1,name:"Based on Antibiogram"}, {id:2,name:"Molecular"}, {id:3,name:"Genetic"}];
$scope.selected = $scope.selectedAlready;
$scope.selectedValues = [];
$scope.$watch('selected', function(nowSelected){
$scope.selectedValues = [];
if( ! nowSelected ){
return;
}
angular.forEach(nowSelected, function(val){
$scope.selectedValues.push( val.id.toString());
console.log("look");
});
});
$scope.showAlert=function(listOfMultipleChoices){
//alert(object);
}
EDIT to add jsfiddle link which is working but I still haven't found solution to original question: https://jsfiddle.net/StevenEvenSteven/ybapx09w/

There is a typo in your code.
Add a comma after '$scope' in your controller definition
fiddleApp.controller('myFiddle', ['$scope', function($scope) {
I've forked your jsfiddle and it is working as you expected.

Related

AngularJS cascaded drop downs, dependant dropdown not filling in

So I have 2 drop downs which need selecting before a third one can be populated.
The problem is even with data coming back the 3rd one isn't populating.
Because of how it is designed each dropdown has it's own controller, with another one for the whole window.
Source widget:
<select class="form-control" required name="dataDomain"
ng-model="customFilters.dataDomain.value"
ng-options="dataDomain.code as dataDomain.shortName for dataDomain in dataDomains"
ng-change="customFilters.dataDomain.loadExtraData()">
<option value="" translate>_NONE_</option>
</select>
source controller:
(function init() {
$scope.customFilters = reportsService.filters;
$scope.customFilters.dataDomain = {
value: undefined,
loadExtraData: function() {
var reportType;
if(this.containsData() && !this.isDisabled()) {
reportType = reportsService.filters.reportType.value;
dictionaryService.getCustomReports({"dataDomain": 'WEE', "country": 'UK')
.then(function ({data}) {
$scope.customReports = data.customReport;
});
}
}
};
})();
The target widget:
<select class="form-control" required name="custom"
ng-model="customFilters.custom.value"
ng-options="c.reportUrl as c.reportName for c in customReports">
<option value="" translate>_NONE_</option>
</select>
whole window controller:
$scope.customReports = [];
As a test to ensure My target widget is looking at the correct location I have also tried in the whole window controller The target dropdown was populated with frank and Joe.
$scope.customReports = [{reportUrl:'hello',reportName:'Frank'},{reportUrl:'hello2',reportName:'Joe'}];
Why isn't the dropdown being populated after the ajax call? (see edit 3)
Edit 1: I have removed excess ajax calls and conditional
functionality from the source widget controller. Hopefully to make
it easier to see. I may have got my brackets wrong.
Edit 2: I did some debugging and the scope ID in the source was 47
and in the target it was 50. I have no idea what these numbers mean,
but it shows I am not storing my data in the same space.
Edit 3: I FIXED IT (by just trying everything), But i don't know why
I moved the customReports data to $scope.customFilters.customReports so the question has changed to WHY IS THIS WORKING!!!!
Because of how it is designed each dropdown has it's own controller,
with another one for the whole window.
This is the key! You have defined $scope.customReports inside wholeController which has a different scope than your dropdown. That is the reason you were able to fix it once you moved it inside $scope.customFilters.customReports which is the same scope as that of the dropdown.
From angularjs documentation
Each AngularJS application has exactly one root scope, but may have
several child scopes.
This blog explains it in detail about Understanding Angularjs scope $rootScope and $scope.

AngularJS dropdown selected values need as JSON

I have multiple dropdowns in my application which are populating through a json (which is a map basically) given in controller.
For first dropdown if I select xyz value, then corresponding xyz1 values should come in dropdown and similarly for third dropdown. This all is happening fine currently. But now I want these user selected values to get in json form so that I can send back to backend for further processing. I am not getting selected values but the wrong second dropdown values if I print on console.
codepen and
working plunker
I understand that you need to get values from the dynamic input elements. For that, you need to set ng-model to the input elements, not to the div.
The below updated part would help.
<div ng-init="pageObjectName.pageObjParam={}" ng-repeat="(key , value) in pageObjectName.pageObjMethod">
<input ng-model='pageObjectName.pageObjParam[key]' value='' placeholder="{{key}} - {{value}}"></input>
</div>
Now you can get those values from $scope.pageObjectName.pageObjParam.
Updated Plunker
EDIT
I hope the above part helped to get value from dynamic input fields. Now I suggest you to update the code block like below to get the selected values from dropdown (ie, use one hidden input field for each select) and you will get what you want.
<select id="pageObj" ng-model="pageObjectName.pageObj" ng-options="key for (key,value) in pageData" ng-change="pageObjectName.pageObjParam.pageObj=pageObjectName.pageObj">
<option value=''>Select Page Object</option>
</select>
<input ng-model='pageObjectName.pageObjParam.pageObj' hidden/>
You can have a look at the same plunker now
Your codepen seems to be confusing and not working. As you already have the implemention for dropdown I will continue from here about how to get the data from the drop down and convert the data into a JSON.
After getting the data from the dropdown create a JSON object and store it.
I have written a small example to show how to store the data.
$scope.selectedState = function(item) {
var output = {};
output.name = item.name;
$scope.viewOutput = output;
};
Update:
I tried hard but could not get the values using angular way. If you are still looking for an answer then we can use basic javascript way. Refer plunker for the same.
$scope.submitMyForm = function() {
/* while compiling form , angular created this object*/
var pgObj = $scope.pageObj;
var pgClass = $scope.pageClass;
var pgMethod = $scope.pageObjMethod;
var pgObjvalue = document.getElementById('pageObj').value;
var pgClassvalue = document.getElementById('pageClass').value;
var pgMethodvalue = document.getElementById('pageMethod').value;
$scope.output = {'object' : pgObjvalue, 'class': pgClassvalue, 'method': pgMethodvalue};
console.log(data);
};
Working Plunker.
P.S: If you figured out the answer using angular way then do let me know after posting it in the answer section.

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

populate a select with ng-grid columns

I've got an ng-grid that I want to be able to search on particular columns. The user enters some text and chooses a column from a dropdown. My UX guy doesn't much fancy the search-field-in-every-column-header that ng-grid supports.
Here is my Plunker:
http://plnkr.co/edit/WofBDA6QQkCDcwDMznzf?p=preview
(I haven't bothered with the text field yet, just worried about the field picker so far)
I've got a method that grabs the field and displayName for each field and populates my select with options, but for some reason, it gives me an empty first option. I don't want an empty one - and certainly not if it's going to look like this:
<option value="? undefined:undefined ?"></option>
I want it to default to a field of my choice (in the plunker example, I want it to default to 'age')
I can't figure out why I'm getting an undefined option - unless it's because the control is being rendered by my getFilterFields() function BEFORE the colDefs are fully defined. I've tried various ways of delaying the getFilterFields()function - I played with init: gridInit parameter, but so far, no joy.
How can I assure that
1] my dropdown contains ONLY valid columns, and
2] one of them is preselected?
It's better to use ng-options and set the model to the option that you want to be selected.
<select ng-model="selectedItem"
ng-options="item.value as item.name for item in filterOptions.filterFields">
</select>
and in the controller, set:
$scope.selectedItem = "age"; // equal to the value of the default option

How to bind a model to an option's value

In Angular 1.2.11, given a controller with:
$scope.produce = { 'apples' : [{ 'variety' : 'granny smith', 'price': 2.00}] }
And a view with
<select ng-model='fruits'>
<option value="0">More Fruits...</option>
<option ng-repeat="p.apple for p in produce" value="p">{{ p.variety }}</option>
</select>
How can I bind 'p' to the value attribute? If I try as above the model is bound as a JSON string, not as the model itself (as it would be if I were able to use ng-options).
I'm working around this now by using an ng-change function that uses the value bound to fruits as a lookup in $scope.produce, but this seems like a workaround rather than a solution.
EDIT: Sorry I wasn't more clear about this: I need to be able to hard code 1+ options into the select list, so using ng-options is not a solution.
Here are some fiddles to help illustrate my problem:
** Using ng-options **
ng-options allows for one element that it uses for creating a default option for use as a label. Two problems with this: if I try to use that <option> for its intended purpose I can't add a second option to the select. On the other hand, if I just try to add one <option> element, it gets placed at the top of the <select> list. No good.
** Using ng-repeat **
I'm unable to bind the model to the value attribute of the <option> element. Instead, the value is stringified JSON, which is not bindable.
You need to use ng-options:
<select ng-model='fruits' ng-options="thisFruit.variety in apples">
</select>
If you need to have an option selected as a default (your "More Fruits" option) then you need to add that to the data before it gets to the repeater, and also set your model $scope.fruits = 0 to make that selection selected by default.

Resources