How to change value in a select with ng-options by code? - html

I'm working on a project with angularjs, in which I have three DDLs on a page (HTML), created by "select" using "ng-options", once I selected the three DDLs, when I selected the first DDL, I put in an initial state the other two (select an option), but it does not happen as they remain with the selected value or blank.
On the side of the controllers in .js, in the variable that is linked to each of the ng-model of the ddl, they set the default object ($ scope.selectedActive= $ scope.default_option;), but it does not work
When you change each of the ddls, I see that class ng-dirty and ng-valid class (class = "molecule_list ng-valid ng-dirty") I think that there goes the problem.
This is the code in the HTML
<select id="ddl_actives" name="ddl_actives" ng-model="selectedActive" class="molecule_list" style="width:180px;" ng-options="active.text for active in Actives_list | orderBy: 'text'" ng-change="Select_molecule(selectedActive)"></select>
<select id="ddl_submission" name="ddl_submission" class="molecule_list" ng-model="selectedsubmission" ng-options="event.text for event in submissionEvent_list track by event.value" ng-change="Select_submission(selectedsubmission)"></select>
<select id="ddl_authority" name="ddl_authority" class="molecule_list" ng-model="selectedauthority" ng-options="authority.text for authority in authority_list | orderBy: 'text'" ng-change="OpenMenu_Authority(selectedauthority)"></select>
this is the code in the .js
How id load each DDL
$scope.loadActives = function () {
var dow_user_id = Cookies.get('username');
EndpointsService.GetList_Actives.query({ dow_user_id: dow_user_id }, {}).$promise.then(function (data) {
$scope.Actives_list = data;
//SCP-513
$scope.Actives_list.unshift($scope.default_option);
$scope.selectedActive = $scope.default_option;
}, function (error) {
if (error.data.Message != undefined)
alert(error.data.Message + '\n' + 'Detail: ' + error.data.ExceptionMessage);
else
alert('An error has occurred while loading the Actives list\nDetail: at service "GetList_Actives"');
});
};
This is an example of the code I use to reset value in the ng-model of the ddl.
$scope.Select_molecule = function (selectedActives) {
$scope.selectedActive = $scope.default_option;
$scope.selectedauthority = $scope.default_option;
};
my expectation is that when selecting the first ddl the other two show the option of (Select an option)

The default option cannot be selected in other dropdowns if it doesn't exist as an option to be selected, i've taken your code and made some adjustments to it.
Here is it :
HTML :
<select id="ddl_actives" name="ddl_actives" ng-model="selectedActive" class="molecule_list" style="width:180px;" ng-options="active.text for active in Actives_list | orderBy: 'text'" ng-change="Select_molecule(selectedActive)"></select>
<select id="ddl_submission" name="ddl_submission" class="molecule_list" ng-model="selectedsubmission" ng-options="event.text for event in submissionEvent_list" ng-change="Select_submission(selectedsubmission)"></select>
<select id="ddl_authority" name="ddl_authority" class="molecule_list" ng-model="selectedauthority" ng-options="authority.text for authority in authority_list | orderBy: 'text'" ng-change="OpenMenu_Authority(selectedauthority)"></select>
Controller :
$scope.submissionEvent_list = [];
$scope.authority_list = [];
$scope.loadActives = function () {
$scope.default_option = {
text: 'default'
};
$scope.Actives_list = [
{
text: 'test',
value: 'a value'
},
{
text: 'test2',
value: 'another value'
}
];
$scope.submissionEvent_list.unshift($scope.default_option);
$scope.authority_list.unshift($scope.default_option);
$scope.Actives_list.unshift($scope.default_option);
$scope.selectedActive = $scope.default_option;
};
$scope.loadActives();
$scope.Select_molecule = function (selectedActives) {
$scope.selectedsubmission = $scope.default_option;
$scope.selectedauthority = $scope.default_option;
};
Notice that the other dropdown are filled with the default option but it's not selected until the change is made in the first dropdown.
Hope this will help.

Related

How to remove the previously selected option from a drop-down menu in a table?

I am making a project on angular 7.It has a table with a column having dropdowns. The dropdown contains various languages. When a language is selected in a particular row, then it shouldn't appear in the dropdown in the subsequent row. How do I do that?
I tried deleting the selected language from the array using splice().But as it deletes the object, it is also not shown in the dropdown.
Following is the html -(it is the row of the table that defines the dropdown, and this row is dynamic)
<tr *ngFor="let field of fieldArray;let i = index">
<td><button class="btn" (click)="deleteFieldValue(i)"><i class="fa fa-trash"></i></button></td>
<td class="select">
<select #selectLang (change)="selected(selectLang.value,i)">
<option value="undefined" disabled>Select Language</option>
<option *ngFor="let lang of languageList" value={{lang.name}} [ngValue]="lang.name">{{lang.name}}</option>
</select>
</td>
<td>
<input id="fileUpload" name="fileUpload" type="file" name="upload_file" (change)=onFileChange($event)>
</td>
</tr>
following is the typescript code -
languageList = [{'name': "Dothraki"},{'name': "Japanese"},
{'name':"German"},{'name':"French"},{'name': "Spanish"}, {'name':
"Russian"}, {'name': "Italian"}];
selectedLang;
optionLang:string;
fieldArray: Array<any> = [];
newAttribute: any = {};
fileUploadName: any;
selected(lang:string,index:number){
console.log(lang);
// this.languageList.splice(index, 1);
for(let i =0; i< this.languageList.length; i++) {
if(this.languageList[i]['name'] === lang) {
this.languageList.splice(i,1);
break;
}
}
}
addFieldValue() {
this.fieldArray.push("hg");
this.newAttribute = {};
}
deleteFieldValue(index: number) {
this.fieldArray.splice(index, 1);
}
openFileBrowser(event:any){
event.preventDefault();
let element: HTMLElement = document.getElementById('fileUpload') as
HTMLElement;
element.click();
}
onFileChange(event:any){
let files = event.target.files;
this.fileUploadName = files[0].name;
console.log(files);
}
you can solve the problem by holding a set of selected languages and display options conditionally based on whether an option/language is selected before or not.
create a Set to hold selected langs
selectedLangs = new Set<string>();
create a view query to get a list of all select elements
#ViewChildren("selectLang") langSelects: QueryList<ElementRef<HTMLSelectElement>>;
whenever a selection is made/changed on any of the select elements re-populate the selectedLangs set
selected() {
this.selectedLangs.clear();
this.langSelects.forEach(ls => {
const selectedVal = ls.nativeElement.value;
if (selectedVal && selectedVal !== "undefined") this.selectedLangs.add(selectedVal);
});
}
whenever a field is deleted just remove that language from selectedLangs
deleteFieldValue(index: number, lang: string) {
this.selectedLangs.delete(lang);
this.fieldArray.splice(index, 1);
}
and when displaying options for a select check if it is currently selected on current select or already selected in another select *ngIf="selectLang.value === lang.name || !isSelected(lang.name)"
<ng-container *ngFor="let lang of languageList" >
<option *ngIf="selectLang.value === lang.name || !isSelected(lang.name)" value={{lang.name}} [ngValue]="lang.name">
{{lang.name}}
</option>
</ng-container>
where isSelected is defined as
isSelected(lang: string) {
return this.selectedLangs.has(lang);
}
here is a working demo with full source https://stackblitz.com/edit/angular-dqvvf5
You can store the langs in an array make a function like
lang = []; //define the array
getLang(i, languageList) {
return i == 0 ? languageList :
this.getLang(i - 1, languageList.filter(x => x.name != this.lang[i-1]))
}
So, you can has some like
<div *ngFor="let a of languageList;let i=index">
<select [(ngModel)]="lang[i]">
<option value="undefined" disabled>Select Language</option>
<option *ngFor="let lang of getLang(i,languageList)"
[value]="lang.name" >{{lang.name}}</option>
</select>
</div>
But I don't like because each change force Angular to calculate all the options. So we are going to improve the code using FormArray and an array langList, and make sure that we can not choose the same language
First our variable and our function changed
langList=[];
getLangForFormArray(i, languageList) {
return i == 0 ? languageList :
this.getLang(i - 1, this.langList[i-1].filter(x => x.name != this.formArray.value[i-1]))
}
We create a formArray
formArray=new FormArray(this.languageList.map(()=>new FormControl(null)))
And in ngOnInit
ngOnInit()
{
this.formArray.valueChanges.pipe(startWith(null)).subscribe(()=>{
//create the langList array
for (let i=0;i<this.languageList.length;i++)
this.langList[i]=this.getLangForFormArray(i,this.languageList)
//check no repeat values
if (value)
{
value.forEach((x,index)=>{
if (this.formArray.value.findIndex(v=>v==x)!=index)
this.formArray.at(index).setValue(null,{emitEvent:false})
})
}
})
}
See that use formArray valueChanges with pipe(startWith(null)) to create at first the langList
The .html
<div *ngFor="let control of formArray.controls;let i=index">
<select [formControl]="control">
<option value="null" disabled>Select Language</option>
<option *ngFor="let lang of langList[i]"
[value]="lang.name" >{{lang.name}}</option>
</select>
</div>
And the demo in stackblitz
Define template that iterates trough form array controls
<mat-form-field *ngFor="let control of formArray.controls; let idx = index">
<mat-select [formControl]="formArray.controls[idx]"
(selectionChange)="onSelectionChange()">
<mat-option [value]="blankLangId">''</mat-option>
<mat-option *ngFor="let lang of langMap.get(idx)"
[value]="lang.id">{{lang.name}}</mat-option>
</mat-select>
</mat-form-field>
Define an array with all possible langs
public langs: LangModel[] = [// here your data]
public blankLangId = 0; // represents an empty selection
Define a Map that is going to hold an array of langs for specific dropdown
public langMap= new Map<number, LangModel[]>();
Define a method that going to be execute every time selection is changed.
public onSelectionChange(): void {
this.normalizeLangsDropDowns();
}
What normalizeLangsDropDowns method is going to do?
Inside this method we will loop trough form array controls
For each form control we will get all selected langs ids expect current form control
Then we will filter initial array of langs to remove selected ids and set the result into the Map.
Let's implement this logic.
Define a method that gets selected values from formControls expect provided index of control.
private getSelectedLangIdsExcludingProvidedIndex(langIndex: number): Set<number> {
return new Set(this.formArray.controls
.map<number>(control => control.value)
.filter((langId: number, index: number) => index!== langIndex && langId!== this.blankLangId)
);
}
Define a method that will return filtered array of langs
private filterLangsForLangIndex(langIndex: number): LangModel[] {
const langIdsToRemove = this.getSelectedLangIdsExcludingProvidedIndex(langIndex);
return langIdsToRemove .size > 0
? this.langs.filter((lang=> !langIdsToRemove.has(lang.id)))
: this.langs;
}
Finally define the normalizeLangsDropDowns method
private normalizeLangsDropDowns(): void {
// loop trough each form control
this.formArray.controls.forEach((langControl: AbstractControl, langIndex: number) => {
// set filtered langs at current index
this.langMap.set(langIndex, this.filterLangsForLangIndex(langIndex));
});
}
Here you go.

Setting default value of HTML select in a child component with data from API call

I have a multi-component form that I want to pre-fill with data from an API call. The data populates correctly for every field except for the selected value for the select tag. The value is correct, it is just not displaying the correct option inside of the select. The rest of the form, made of input fields, fill in with the correct data.
The child component takes in a form group and that is what fills in the fields.
I have tried .setValue, .patchValue, [(ngModel)], etc. I cannot get the default value to display correctly. What am I doing wrong?
child-component.html
<select [attr.id]="reasonCode" formControlName="reasonCode" placeholder="Reason Code" style="max-width: 100% !important"
no-padding selected>
<option value="" >Please select reason code</option>
<option *ngFor="let reasonCode of reasonCodesService.reasonCodes">
{{reasonCode}}
</option>
</select>
child-component.ts
#Input() newReqForm: FormGroup;
parent-component.html
<div *ngFor="let control of newForm.controls['requisitionItem'].controls; let i = index" style="border: 1px solid black; border-radius: 10px; margin-top: 10px;">
<edit-items (remove)='onRemove($event)' [newReqForm]="newForm.controls.requisitionItem.controls[i]" style="padding-bottom: 10px"
[index]='i'></edit-items>
</div>
parent-component.ts
ngOnInit() {
this.employeeService.loadEmployees();
this.reasonCodesService.loadReasonCodes();
this.itemReqId = +this.route.snapshot.paramMap.get('ReqId');
this.reqService.getRequisition(this.itemReqId).subscribe(response => {
this.editReq = response;
console.log("EDIT REQ VVV");
console.log(this.editReq);
this.editRI = this.editReq.requisitionItem;
this.newForm = this.fb.group({
employee: [this.editReq.employee, Validators.required],
job: [this.editReq.job, Validators.compose([Validators.pattern("^[0-9]+$")])],
requisitionItem: this.fb.array([
])
});
this.arrayControl = <FormArray>this.newForm.controls['requisitionItem'];
this.editRI.forEach(item => {
let newItem = this.fb.group({
item: [item.item, Validators.required],
quantity: [item.quantity, Validators.compose([Validators.required, Validators.pattern("^[0-9]+$")])],
reasonCode: [item.reasonCode],
operation: [item.operation],
})
this.arrayControl.push(newItem);
this.setValidators()
});
for (let i = 0; i < this.arrayControl.length; i++) {
this.arrayControl.controls[i].get('reasonCode').setValue(this.editRI[i].reasonCode);
}
this.setValidators();
console.log(this.editReq);
this.newReqForm = this.newForm;
});
}
My node/Angular info:
Angular CLI: 6.0.8
Node: 8.11.2
OS: win32 x64
EDIT
child-component.ts
isSelected(reasonCode) {
if (reasonCode == this.rc) {
return reasonCode
}
}
You are missing a binding on selected of the selected option (see here). You can set the value of the select using reactive forms but this does not actually select an option.
In other words, you need to add something like [selected]="isSelected(reasonCode)" to option:
<option *ngFor="let reasonCode of reasonCodesService.reasonCodes" [selected]="isSelected(reasonCode)">
{{reasonCode}}
</option>
You can implement isSelected for example by comparing its parameter with the value obtained from the FormGroup reference.

Empty row in ng-option still apears in select menu

Hi I have select menu that should not have empty row, this is my code in AngularJS
$scope.GetAllSnimateljiBaseInfo = function () {
$http.get(serviceBase + "GetAllSnimateljiBaseInfo", { timeout: 6000 })
.success(function (response) {
$scope.snimatelji = response;
$scope.snimatelji.splice(0, 0, { "IDsnimatelj": 0, "Ime": "", "Prezime": "" });
$scope.selectedSnimateljInfilterVideoKlip = $scope.snimatelji[0];
})
.error(function (response, status) {
if (status == 401) {
$state.go('/');
}
else {
alert(response.Message);
}
});
};
this is HTML code
<div class="form-group">
<label class="col-lg-3">Snimatelj:</label>
<div class="col-lg-9">
<select class="form-control" ng-options="column as column.Ime +' '+ column.Prezime for column in snimatelji" ng-model="selectedSnimateljInfilterVideoKlip">
<option value=""></option>
</select>
</div>
</div>
But select menu looks like this
As you can see I have two empty menu options instead of one ?
Where is my mistake , any help please ?
Regards
By default one empty row will be there for angular select. The additional empty row is because you have specified
<option value=""></option>
in select tag- remove that.
If you would like to remove the default empty row as well, then set
$scope.selectedSnimateljInfilterVideoKlip = $scope.snimatelji[0]
or use ng-init to achieve the same.

Autofill html select AngularJS

I have a little issue with a HTML select with AngularJS. When I do a petition to my API I get one of the values as an integer, but when I try to autofill a select with it I can't set de "value" correctly.
In this picture you can se what the HTML is receiving and the values that I want to set
Are there any way to cast this value?
Thanks in advance :)
EDITED:
The controller to get customer data and fill the form
.controller('CustomerDetailCtrl', ['Customer', '$scope', '$sessionStorage', '$stateParams', '$ionicPopup', function (Customer, $scope, $sessionStorage, $stateParams, $ionicPopup) {
if ($sessionStorage.auth) {
Customer.get({data: $stateParams.customerId + '_' + $sessionStorage.user_id}).$promise.then(function (data) {
if (data.response && $sessionStorage.role === 1) {
$scope.customer = data.response[0];
if (data.history) {
$scope.histories = data.history;
}
} else {
console.log('Error de accesso...');
}
})
}
$scope.addTask = function (customer) {
alert('add task!');
}
$scope.deleteTask = function (customer, history) {
alert('delete task!');
}
}])
The form:
<label class="item item-input item-select">
<div class="input-label">
Cliente avisado?
</div>
<select name="informed" ng-model="customer.informed" required>
<option value="0">NO</option>
<option value="1">SI</option>
</select>
</label>
And here a picture of the data from de API:
I know that you've already received an answer on this, but I wanted to show you one other potential option that doesn't involve having to change your data from an int to string. If you define the options for your select in your controller (or in a service if this will be used in multiple different places throughout your app) then you can take advantage of ng-options and its ability to use a value other than a string.
Here's an example (obviously I've hardcoded some things and put this all in a single module - not something you'd do in a real app).
JS:
angular.module('app', [])
.controller('ctrl', function($scope){
// select options (if these are common maybe store them in a service
// so you can share them in many controllers without duplicating the code)
$scope.selectOptions = [
{
text: 'NO',
value: 0
},
{
text: 'SI',
value: 1
}];
// sample data
$scope.customer = {
address: 'San Rosendo 11',
date: '2016-03-16T16:19:13+0100',
email: 'Montes',
equipment: 'PC',
id: 262,
informed: 1,
lastName: 'Montes',
location: 'Tienda',
name: 'Juanma',
notes: '',
pass: 'no tiene',
phone: '900112233',
price: '0',
status: 'Pendiente',
tasks: 'dfsdf'
};
});
HTML:
<div ng-app='app' ng-controller='ctrl'>
<select ng-model='customer.informed' ng-options='option.value as option.text for option in selectOptions'></select>
</div>
jsFiddle
Define a default value somewhere in your controller: $scope.customer.informed = "NO";

Select2 acts very different with Uncaught query function not defined for Select2 <select2-id>

I load values for select2 like the following way.
Declare the Type
var AdjustmentType = Backbone.Model.extend({
url : Hexgen.getContextPath("/referencedata/adjustmenttype")
});
create instance for the Type
var adjustmentTypes = new AdjustmentType();
load the values to select2 box
adjustmentTypes.fetch({
success : function() {
for(var count in adjustmentTypes.attributes) {
$("#adjustment-type").append("<option>" + adjustmentTypes.attributes[count] + "</option>");
}
}
});
$("#adjustment-type").select2({
placeholder: "Select Adjustment Type",
allowClear: true
});
My HTML Code
<div class="span4">
<div>ADJUSTMENT TYPE</div>
<select id="adjustment-type" tabindex="5" style="width:200px;">
<option value=""></option>
</select>
</div>
when i load this for the first it is not giving any exception but if i Refresh or navigate to different URL i get the following exception:
Uncaught query function not defined for Select2 adjustment-type
"Query" refers to the list by which to check your search terms against. You need to make sure that your data property is a proper array of objects (ie. your options elements).