So I have the following code:
<div class="form-group">
<label for="backings_select">Backing Single</label>
<select class="form-control"
required
[(ngModel)]="selectedBacking"
name="backings_select"
(ngModelChange)="storeValueRedux($event, count)">
<option *ngFor="let backing of backings" [ngValue]="backing.id" [selected]="backings.length === 1">{{backing.name}}</option>
</select>
It populates a select box with results from a service call, if the array length is 1, it auto selects the only option available, this works fine.
However, by default the select box uses a value from the component as its default value.
So when the service call is made, if the array only has a length of one, the value of the model is changing, but because its being auto selected (not by user input) the storeValueRedux event is not firing.
However, if the array has more than one entry, and then is selected by a user, the function is called and works as required. Is there anyway to trigger ngModelChange in the instance that backings.length = 1?
You can't use a condition inside your method calls in HTML but you can use change and handle the condition inside your method as below
<select class="form-control"
required
[(ngModel)]="selectedBacking"
name="backings_select"
(change)="storeValueRedux($event, count)">
<option *ngFor="let backing of backings" [ngValue]="backing.id"
[selected]="backings.length === 1">{{backing.name}}</option>
selectedBacking:any{};
backings:any[]=[
{id:1, name:'a'},
{id:2, name:'a'}
]
storeValueRedux(a,b){
if(this.backings.length!=1){
console.log(this.selectedBacking);
console.log(a,b);
}
}
LIVEDEMO
The service that returned my backings was an observable, so I modified the subscribe from:
.subscribe(
results => {this.backings = results},
error => console.log(error),
);
to:
.subscribe(
results => {this.backings = results, this.testBackingLength()},
error => console.log(error),
);
And then added:
testBackingLength(){
/* If the length of the arrau is only one, the template auto selects it
and does not trigger ngOnChange, so we need to manually trigger it here,
this function is called from the subscribe a few lines up */
if (this.backings.length === 1) {
this.storeValueRedux(this.backings[0]['id'], this.count)}
}
So each time my service is called, it tests the length of the array. If the length of the array is 1, it will auto call my function.
Related
I have this that takes the value and send it to my backend along with others in a form
<select
v-model="formData.account_bank"
id="branch"
#change="getbranch"
>
<option v-for="bank in selectBank" :key="bank.id" :value="bank.code">{{
bank.name
}}</option>
</select>
but before it is sent I need to get some data to populate a second selectbox using bank.id which I should have as :value = "bank.id" in the code above.
To get the value to make the api call that populates the second selectbox I just do
var branch = document.getElementById('branch').value;
and use it in the API call.
But here I need to get the bank.id to make the first api call that populates the selectbox and still have the bank.code there as form data to submit.
I have thought about getting the key using javascript which has the bank.id. But can not figure how or a different way it should work.
One solution to this problem is to bind the entire bank object to your <select> model.
Then you can use its id to populate your other select options and its code to construct your form data payload.
For example
<select
v-model="selectedBank"
id="branch"
#change="getbranch"
>
<option v-for="bank in selectBank" :key="bank.id" :value="bank">{{
bank.name
}}</option>
</select>
data: () => ({
formData: {
// whatever you originally had here
},
selectedBank: {} // empty object or perhaps a default bank
}),
methods: {
getBranch () {
const bankId = this.selectedBank.id
// make API call, etc
},
submitForm () {
// build form data
const formData = {
...this.formData,
account_bank: this.selectedBank.code
}
// submit form, etc
}
}
See https://v2.vuejs.org/v2/guide/forms.html#Value-Bindings
I am grabbing some items through a http call and then want to pre-populate the ngselect, but using the abstractcontrol.setvalue() method does not seem to work.
Template Code
<ng-select [items]="cars"
bindValue="code"
bindLabel="displayName"
formControlName="car"
[clearable]="false"
[searchable]="false"
id="car"
placeholder="Select a car">
Component Code
this.setValueForPrePopulatedPlanningDetail('car', car);
private setDefaultValue(fieldName: string, value: any) {
if (value && value.length > 0) {
const field = this.myFormGroup.get(fieldName);
field.markAsDirty();
field.setValue(value);
}
}
You need set your result to the list (countries) and then use setvalue to choose the option
Set result to your list in your component:
this.countries = ['XPTO','XPTO2','XPTO3']
Define the following in your html:
<select>
<option [value]="country" *ngFor="let country of countries"> {{country}}</option>
</select>
The right way of using ng-select, would be to assign the values to the items input binding.
For instance,
<ng-select [items]="cities2"
bindLabel="name"
bindValue="id"
[multiple]="true"
placeholder="Select cities"
[(ngModel)]="selectedCityIds">
</ng-select>
And on your component.ts, you will populate ng-select options by subscribing to the observable returned by the HTTP request, and assigning it the cities2 property.
cities2: any[] = [];
ngOnInit() {
this.dataService.getData.subscribe(res => {
this.cities2 = res;
});
}
This demo might not directly answer your queries, but it shows how the various input bindings (such as items) work with ng-select.
I am trying to show the initial value of a array of objects like this:
tableStyes[
{Id: 1, style: "blabla1},
{Id: 2, style: "blabla2"}
]
basicly i am using a computer method to give me the array from vuex store
tableStyles () {
return this.$store.getters.getTableStyles
},
i am doing the select this way:
<select class="form-control" v-model="table.tableStyle">
<option v-for="(item,key) in tableStyles" :value="item.Id">
{{ item.style }}
</option>
</select>
i want to get the value based on the id, i mean i want to get the text associated to the id, and the id is table.tableStyle, that is 1 at the begin that should be the selected item, but somehow it doesn't work :/.
Any help?
You need no computed method to display data from vuex store.
v-model="table.tableStyle" sets the first displayed item, if it is initialized with anything that is not included in the array, no item will be selected before you select one manually.
Try:
data:{
return {
...
table.tableStyle: this.$store.getters.getTableStyles[0]
}
}
I dont know if this works in data section.
In web app I have a list of Expenses, which that if you press above it takes you to a new page to edit the selected Expense. When the user click on an element of list, I save the Object (the selected Expense) in a Global Object common in whole application and I retrieve it when I am in the Editing controller:
$scope.companySelected = GlobalApplicationData.selectedExpenseList;
The GlobalApplicationData.selectedExpenseList is an Object:
$$hashKey: "object:39"
_id: "33aa5549-7802-40d9-bc89-8780705b8c9b"
_rev: "3-eb940cb990524112723f711618e0cf51"
ad_table_id: 1000596
company_name: "Company 1"
data: Object
recordid: 1000005
__proto__: Object
In one expense there is only one company.
So, in this page of editing I have some field (input type text, date, etc). And I also have a selection with the list of the Companies of the logged user. To retrieve that list, I made this function:
$scope.getCompanyList = function() {
EditExpenseListSrv.getCompanyListDetail(user).then(function (companyListDetail) {
$scope.companyList = companyListDetail;
$scope.$apply();
}).catch(function (err) {
console.log(err);
});
};
CompanyListDetail is an array of Obejct:
companyListDetail: Array[5]
0: Object
1: Object
2: Object
3: Object
4: Object
And this is one example of those object:
_id: "44e620dc-e715-453f-882b-3f21aeef48fe"
_rev: "1-c09c9f3350e853e588f3358aaafc0374"
ad_table_id: 1000146
data: {
description: "text"
id_company: 513424
name: "Company 2"
}
recordid: 1000002
So the company of the selected Expense ($scope.companySelected) will definitely part of the list obtained by the query ($scope.companyList). But I want to give the user the possibility to change it.
So I would like to make a selection containing the list ($scope.companyList) and default already selected the Company corresponding to $scope.companySelected.
I've writter this, but it doesnt work:
<select class="selection" ng-model="companySelected"
ng-init="companySelected = globalApplicationData.selectedExpenseList"
ng-options="company
as company.data.name for company in companyList">
But it doesn't work. I can see in the selection all the Companies, but don't select the default value
When you are assigning a default value to the select, you need to assign the object, so it won't work, when assigned with the same data of some other object:
Note:
a) data is the array which is getting looped in the select list
b) selectedcountry is the model which is bind on select list.
Option 1:
Using ng-init:
<select ng-model="selectedcountry" ng-init="selectedcountry = data[0]" ng-options="item.name for item in data">
<option value="">Select</option>
</select>
Demo 1.
Option 2:
Assigning the default from the controller
$scope.selectedcountry = $scope.data[0];
Demo 2
You can try to do the initialisation in the controller:
$scope.companySelected = "the value that you want to set here"
Or you can try to put the ng-init inside the parent of the select. Once I had a problem like this and I solved it putting the ng-init in the parent tag. Example:
<div id="parent" ng-init="companySelected = globalApplicationData.selectedExpenseList">
<select ...>
</div>
Another idea would be to put companySelected inside an object. I have had some problems (I am not sure why) with the forms if I was using $scope.value inside the ng-value instead of using $scope.formData.value
Sup guys! I am trying to build a dynamic form, but I got stuck in a ngModel problem.
The idea is:
I got 2 arrays: one for temporary show to user selected info, and another that is which actually is saved on post (I have different types of data, so I have to do this way).
1- The user uses a <select> to choose a option. The selected option is a object inside a list. User hits the add link, and the selected option pop for him.
2- The selected option, has a custom property, that must be set before hit the add button. For that, a ´input´ pop when an option is selected. the ngModel for this is dynamically set, based on a object's property.
3- I need to get the input data, and save it inside a property of the object selected on the list.
4- Push the object to the array-to-be-posted (newData).
What I have that work: the list, the dynamic ngModel.
What I need: to get the data from this ngModel ad use it inside my directive.
here go the codes:
html:
<select id="newPrereq" class="form-control" name="newPrereq" ng-model="newPrereq" ng-options="prereq.name group by prereq.cat for prereq in prereqs | orderBy:prereq.name">
<option value="" hidden>-- Select --</option>
</select>
<input type="{{newPrereq.type}}" ng-show="newPrereq.array" ng-model="newPrereq[ngModel]">
<a ng-click="addItem(newPrereq, selectedPrereqs, 'prereqs')" ng-show="newPrereq !== undefined || ''">add</a>
<ul class="list-inline">
<li ng-repeat="prereq in selectedPrereqs"><span>{{prereq.name}} </span> <a ng-click="removeItem($index, selectedPrereqs, 'prereqs')">[X]</a></li>
</ul>
directive (scope:false) relevant functions:
scope.prereqs = Lists.prereqs;
scope.addItem = function(obj, array, group){
array.push(obj); // Add item to array-to-be-posted
if(obj.array){
scope.newData.prereqs.proficiencies.push({'name': obj.name, 'cat': obj.cat, 'details': [something here to get the ng-model from DOM]})
};
scope[group] = scope[group].filter(function(list){ // Remove added item from the <select>
return list !== obj;
});
scope.newPrereq = undefined;
};
part of the list (come from a Lists.js service)
'prereqs': [
{'name':'option 1', 'cat':'category 1', 'type':'text', 'ngModel':'smDetails', 'array':true},
{'name':'option 2', 'cat':'category 2', 'type':'text', 'ngModel':'srDetails', 'array':true},
]