change event on updated model - javascript

I have a list of fields
fields: [
{
id:0,
label: 'dropdown 1',
value: 0,
options: [{ id: 0, value: 0, label: 'Option 1' }]
},
{
id: 1,
label: 'dropdown 2',
value: 0,
options: [
{ id: 0, value: 0, label: 'Hide dropdown 1' },
{ id: 1, value: 1, label: 'Show dropdown 1' }
]
}
]
that are filtered before being shown like so:
<div v-for="field in fields.filter(ffield => showField(ffield))" :key="field.id">
<b-form-select v-model="field.value" #change="changed(field)">
<option v-for="option in field.options" :key="option.id" :value="option.value">
{{ option.label }}
</option>
</b-form-select>
</div>
I can hide 'dropdown 1' based on the selected option in 'dropdown 2'. This is managed by the 'showField' function:
function showField(field) {
return field.value !== 'dropdown 1' || fields[1].value === 1
}
Lets say dropdown 1 is hidden and I select the second option Show dropdown 1. Vue's reactivity runs the showField function for all items in the list before running the changed event on the affected field. So now dropdown 1 is visible and then the eventhandler is called.
But what's really weird is that the parameter field in the changed function corresponds to the value of fields[0] even though I selected an option in 'dropdown 2' or fields[1].
What is going on?
I understand that this doesn't happen when dropdown 1 is after dropdown 2 in the list.
I tried modifying node_modules/bootstrap-vue/esm/components/form-select/form-select.js rendering function but this must be some internal thing that's causing it and I'm not familiar enough to keep digging.
Maybe I disregarded some pattern for this sort of thing?
The filter in the v-for came in because we used v-if="showField(field)" together with the v-for and that was incorrect.
How can I avoid this?

Related

How can we use the "name" or "id" attribute values as the data property in Vue JS?

I am working on an SPA application where I have a list of data variables that are used as the <option> tags in the dropdown. I want to navigate to another page on the #change event of the dropdown therefore I want to use either the id or name of the select command as the name of the data property. Here is what I mean:
Here is what I have in the data function:
data(){
return {
participants: [
{ value: 0, linkText: '', linkTerm: 'Select' },
{ value: 1, linkText: '/meetings/participants/create', linkTerm: 'Add New' },
{ value: 2, linkText: '/meetings/participants', linkTerm: 'All Participants' },
],
positions: [
{ value: 0, linkText: '', linkTerm: 'Select' },
{ value: 1, linkText: '/meetings/positions/create', linkTerm: 'Add New' },
{ value: 2, linkText: '/meetings/positions', linkTerm: 'All Positions' },
],
}
}
Here is the select tag where I use the above data variables as the <option> tag:
<select name="participants" id="participants" class="select-field" #change="changeRoute($event)">
<option v-for="p in participants" :value="p.value">{{ p.linkTerm }}</option>
</select>
Now I want to have one function changeRoute($event) from which I will navigate to different pages, therefore I want to use the id or name value as the data property, here is the function:
methods:{
changeRoute($event){
var name = $event.target.name;
var value = document.getElementById($event.target.id).value;
}
}
Here in the above function I want to use the name as the data property as below:
I want to write this:
this.name[value].linkText;
And because name here is the name of the tag which is actually participants so the above line of code should mean something like this:
this.participants[value].linkText
And that should return the linkText of the participants object of the data function.
Any help is appreciated in advance.
Change the below line
this.name[value].linkText;
to
this[name][value].linkText;

v-if and splice on users pick from v-model

I have the following code (from a tutorial, but I want to expand it a bit):
<div style="margin-top: 10px;">
v-for="task in taskItems"
:key="task.id"
<q-icon :name="task.icon"/>
<div
{{ task.text }}
</div>
</div>
my taskItems array looks like this:
taskItems: [
{
id: 1,
icon: 'settings',
text: 'Dolor, sit amet consectetm tot',
name: 'style'
},
{
id: 2,
icon: 'exit',
text: 'Lossssr dolor, sit amet consectetm tot',
name: 'getaway'
},
{
id: 3,
icon: 'lego',
text: 'Lomet consectetm tot',
name: 'buildingblocks'
},
{
id: 4,
icon: 'lego',
text: 'Lomet consectetm tot',
name: 'buildingblocks'
}
]
and I have the following v-model:
numberOfTasks: [
{ value: '1', label: '1' },
{ value: '2', label: '2' },
{ value: '3', label: '3' },
{ value: '4', label: '4' },
}
where a user can pick an object by clicking on a button (left out since that isn't the primary focus) and if they choose the first, then it is equal to value '1', if they choose the second, then it's equal to '2', etc.
The thing is, that I want my v-for at the top, which contains 4 tasks, to show the number of elements from its array equal to the numberOfTasks, that the user chooses.
So if the user chooses value: '3', then the v-for will only show 3 tasks from the tasks array.
I am new to Vue and have tried several things out, but none works.
How do I bind these together and do I need to use task.splice in my ?
Anyone have an idea, what to do?
I'll assume taskItems is a property of data as well as numberOfTask which store the value choosen form numberOfTasks.
You need to change v-for="task in taskItems" in v-for="task in actualTaskItems" where actualTaskItems is a computed property like so
// …
computed: {
actualTaskItems() {
return this.taskItems.splice(0, this.numberOfTask);
}
}
This is freehand so it might not be 100% correct, but you can simulate an index for loop in Vue. I've added a variable selectedNumberOfTasks which would just be a number (a data variable or something) that represents what the user has selected.
<div v-for="index in selectedNumberOfTasks" :key="index">
{{ taskItems[index].text }}
</div>
This will count up in the variable index to a max of selectedNumberOfTasks.
The JS for loop equivalent would be
for (let i = 0; i < this.selectedNumberOfTasks; i++)

Showing selected option in dropdown with opt-group on page load AngularJS is not working

When I try to show default selected value it doesn't show up i.e the option does not get selected in dropdown. The default value is coming from database and I'm setting that value in the model variable pageData.fields[content.id].keyFollowing is the sample JSON that I'm using to populate the dropdown:
$scope.dropdownFields = [{
groupName: 'PAGE',
isOptDisabled: false,
items: [{
name: 'PageName1',
type: 'page'
},
{
name: 'PageName2',
type: 'page'
},
{
name: 'PageName3',
type: 'page'
},
{
name: 'PageName4',
type: 'page'
}
]
},
{
groupName: 'COLOR',
isOptDisabled: false,
items: [{
name: 'COLOR1',
type: 'component'
},
{
name: 'COLOR2',
type: 'component'
},
{
name: 'COLOR3',
type: 'component'
}
]
},
{
groupName: 'OTHERS',
items: [{
name: 'Bold',
type: 'others',
isOptDisabled: false,
itemList: [{
name: 'Yes',
value: true
},
{
name: 'No',
value: false
}
]
},
{
name: 'Italic',
type: 'others',
isOptDisabled: false,
itemList: [{
name: 'Yes',
value: true
},
{
name: 'No',
value: false
}
]
}
]
}
];
<select id="{{content.id}}_filter" ng-model="pageData.fields[content.id].key" class="form-control" ng-change="onChangeFilter(pageData.fields[content.id].key, content.id)">
<option value="">[Select an option]</option>
<optgroup ng-repeat="header in dropdownFields" label="{{ header.groupName }}">
<option ng-repeat="item in header.items" value="{{ item.name }}" ng-disabled="isDisabled(header.groupName, item.name)">{{ item.name}}
</option>
</optgroup>
</select>
Is there any way to do this as I've researched a lot on this but the solutions were with ng-options and I cannot use ng-options for creating the dropdown due the disability functionality. The AngularJS version that I'm using is 1.2Any suggestion into the direction will be appreciated. Thanks.
EDIT: The code is successfully populating the dropdown and I'm able to get the value of selected option as well. But I'm not able to set an option by default into the dropdown. For eg. PageName3 is already selected in the dropdown.
EDIT2: So far now I'm able to show default value selected in this combobox on button click(here's the plnk) but I'm not able to set this value when I redirect from another page to this page.
So it goes like this, on this page(say PAGE1) I fill in these values there are multiple such dropdowns and textboxes in front of them for values, then I pass these values to the next page(say PAGE2); on PAGE2 I have a back button on the click of this button I return to PAGE1 with the same values passed before and I've to set all these values back as it were before. This is where I'm stuck! Not able to set selected values in dropdown while setting textboxes is done.
You can add default option into dropdown like so:
<input type="checkbox" ng-model="selected"></label><br/>
<select ng-model="item.name" ng-click="onChangeFilter(item.name)" class="form-control" >
<optgroup ng-repeat="header in dropdownFields" label="{{ header.groupName }}">
<option ng-selected="selected">Greetings!</option>
<option ng-repeat="item in header.items">{{item.name}}</option>
</optgroup>
</select>
plunker: http://plnkr.co/edit/vszVo3BHEA3T4yxGSUkA?p=preview

How to use the text attribute from options in a form select with V-Model

I currently have a vue bootstrap form with several inputs, one being a select.
<b-form-select id="myInput"
:options="listOfOptions"
v-model="form.selection"
required>
</b-form-select>
With options being:
listOfOptions: [
{
text: 'Option A',
value: 'A'
},
{
text: 'Option B',
value: 'B'
},
{
text: 'Option C',
value: 'C'
},
],
As expected, when I select one, it sets form.selection to the value I have chosen, so if I select 'Option C', form.selection is set too 'C'.
I now have another requirement. I need to assign the value of text to a new variable in form, lets call it name. So when I select 'Option B' form.selection = 'B' and form.name = 'Option B'. I've been playing around, but can't seem to get it right.
The bootstrap select component is designed this way and if want to has the text as part of data that you select, you must change the source:
listOfOptions: [
{
text: 'Option A',
value: {
text: 'Option A',
value: 'A'
}
},
...
]
Now, form.selection is an object that you have them.

AngularJS and Select

I'm having trouble understanding why my Angular <select> doesn't add the default value to the category I want.
I have an object that is returned from our database in Parse; the object is like this ( this is the "selected" option ):
$scope.item.category = { id: 'uosDHIF', className: 'Category', name: 'Projects' }
And I have a list of categories also:
$scope.categories = [{ id: 'uosDHIF', className: 'Category', name: 'Games' }, { id: 'uosDHIF', className: 'Category', name: 'Random' }, { id: 'uosDHIF', className: 'Category', name: 'Projects' }]
In my HTML what I have it's a select like this:
<select name="category" class="form-control mb-10" ng-model="item.category" ng-options="category.name for category in categories"></select>
I can select a new category and it's assigned to the item, and then I can save the item with item.save() but what I have trouble doing is that the selected (ng-model) doesn't seem to work, when I enter the page the first time I always get the default blank option even if I have the category when I check in the console.
Also, I was able to make it work with a simple object that I have created myself, but this object is returned from our database in Parse, so I'm not sure if this is the problem or I'm just missing something in there.
Thank you for your help.
Note: I have read other StackOverflow problems similar to mine but they doesn't help with mine.
In fact, on ng-options, you have to specify the value for the model (category as category.name => you choose category for ng-model but display it by his name).
The matching occurs by reference so you need the same object (category : $scope.categories[0]).
You can try:
JS
$scope.categories = [
{ id: 'uosDHIF', className: 'Category', name: 'Games' },
{ id: 'uosDHIF', className: 'Category', name: 'Random' },
{ id: 'uosDHIF', className: 'Category', name: 'Projects' }
];
$scope.item = {
category : $scope.categories[0]
};
HTML
<select name="category" class="form-control mb-10" ng-model="item.category" ng-options="category as category.name for category in categories"></select>
Please change the html as below.. Hope this is helpful.
ng-model="item.category.id" ng-options="category.id as category.name for category in categories">

Categories