React state object attribute is getting set as undefined - javascript

I have the following state object initialized called myCriteria
const [myCriteria, setMyCriteria] = useState({
myFieldStatusDropdown: myFieldStatusDropdown,
selectedMyFieldStatus: myVarMyFieldStatusDropdown?.value,
});
Now I have the breakpoint set right above this line
setMyCriteria({
...myCriteria,
selectedMyFieldStatus: myCriteria.myFieldStatusDropdown[0]
});
and at the breakpoint, I inspect and see myCriteria.myFieldStatusDropdown as below
[
{
code: 'Select',
value: 'Select'
}, {
code: 'AA',
value: 'A 1'
}, {
code: 'BB',
value: 'B 1'
}
]
However for some strange reason, after the setMyCriteria line is executed, when I inspect the value of myCriteria.selectedMyFieldStatus, it is wrong
i.e. instead of it being set to
{
code: 'Select',
value: 'Select'
}
it is getting set as undefined
Not sure why it gets set as undefined

I simply initialized using myCriteria and put three objects in it, in form of an array
var myFieldStatusDropdown = [
{
code: 'Select',
value: 'Select'
}, {
code: 'AA',
value: 'A 1'
}, {
code: 'BB',
value: 'B 1'
}
]
const [myCriteria, setMyCriteria] = useState({
myFieldStatusDropdown: myFieldStatusDropdown,
selectedMyFieldStatus: myFieldStatusDropdown[1]
});
then I use setMyCriteria to update the myCriteria
setMyCriteria({
...myCriteria,
selectedMyFieldStatus: myFieldStatusDropdown[0]
},[myCriteria]);

Related

How to map data depending on whether I ever get different objects? JS Angular 2+

I need to filter through, but the problem is that the knowledge I get changes its properties
First example of object ( of arrays )
{ name : 'test' , value: 'Values 1' },
{ name :'test 2' , value: 'Values 2' }
And when i filter this is easy:
<span *ngFor="let date of dates">
{{ date.value }}
</span>
But second time i got different data
{ name : 'test' , value: 'Values 1' },
{ name :'test 2' , value: 'Values 2' }
{ name :'test 3' , value: [{name :'test 3' , value: 'Values 3'}] },
{ name :'test 4' , value: [{name :'test 4' , value: 'Values 4'}] }
I need to filter this data and show only value ( last value )
the menu is currently displayed result example:
Values 1 , Values 2, [Object Object] , [Object Object]
You could NgIf and check if date.value is typeof array, if yes and its only 1 object, then make it display {{date.value.value}} else if its not an array display {{date.value}} ... sorry I can't type specifics
You can use map to modify the array of objects as per your need.
dates.map(x=>{
if(Array.isArray(x.value))
x.value = x.value[0].value
return x;
});
The result will be
[{ name : 'test' , value: 'Values 1' },
{ name :'test 2' , value: 'Values 2' }
{ name :'test 3' , value: 'Values 3'},
{ name :'test 4' , value: 'Values 4' }]
Update: if you want to print all the values, you can join them using map function, this will work for n objects inside value array.
dates.map(filerVal => {
if (Array.isArray(filerVal.value)){
filerVal.value = filerVal.value.map(v=>v.value).join(' ');
}
return filerVal;
});
stackblitz link.
let me know if this is what you expect.

Document.getElementsByClassName has 0 length but has elements inside

[![Firefox Console][1]][1]In my Vue app I am trying to use mdb-datatable, the table reads data() and sets the rows accordingly. I am setting the row data programmatically after my data is loaded with Ajax. In one column I need to add a button and it needs to call a function. I am trying to add onclick function to all buttons with "status-button" class but something weird happens.
When I print HtmlCollection it has a button inside, which is expected but I can't reach proceedButtons[0], it is undefined. proceedButtons.length also prints 0 length but I see the button in console.
I also tried to add onclick function but probably "this" reference changes and I get errors like "proceedStatus is not a function" it does not see anything from outer scope.
<mdb-datatable
:data="tableData"
:searching="false"
:pagination="false"
:responsive="true"
striped
bordered/>
export default {
name: "Applications",
mixins: [ServicesMixin, CommonsMixin],
components: {
Navbar,
Multiselect,
mdbDatatable
},
data () {
return {
statusFilter: null,
searchedWord: '',
jobRequirements: [],
applications: [],
options: ['Awaiting', 'Under review', 'Interview', 'Job Offer', 'Accepted'],
tableData: {
columns: [
{
label: 'Name',
field: 'name',
sort: 'asc',
},
{
label: 'Date',
field: 'date',
sort: 'asc'
},
{
label: 'Compatibility',
field: 'compatibility',
sort: 'asc'
},
{
label: 'Status',
field: 'status',
sort: 'asc'
},
{
label: 'Proceed Application Status',
field: 'changeStatus',
}
],
rows: []
}
}
}
fillTable(applications) {
let statusButtonId = 0;
applications.forEach(application => {
this.tableData.rows.push({
name: application.candidateLinkedIn.fullName,
date: this.parseDateFromDateObject(application.applicationDate),
compatibility: this.calculateJobCompatibility(application.candidateLinkedIn.linkedInSkillSet),
status: application.applicationStatus,
changeStatus: '<button type="button" class="btn-indigo btn-sm m-0 status-button"' +
' style="margin-left: 1rem">' +
'Proceed Status</button>',
candidateSkillSet: application.candidateLinkedIn.linkedInSkillSet
});
statusButtonId++;
});
},
addEventListenersToButtons() {
let proceedButtons = document.getElementsByClassName("status-button")
console.log(proceedButtons);
console.log(proceedButtons[0])
console.log(proceedButtons.item(0))
/*
proceedButtons.forEach(button => {
button.addEventListener("click",this.proceedStatus);
});
*/
},
[1]: https://i.stack.imgur.com/zUplv.png
From MDN:
Get the first element with a class of 'test', or undefined if there is no matching element:
document.getElementsByClassName('test')[0]
So undefined means no match, even if length is 0...
Since this is not an array, you do not get out-of-bounds exceptions.
https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementsByClassName
Regarding Arrays
You can't index the list returned from getElementsByClassName.
You can turn it into an array though, and then index it.
ES6
let proceedButtons = document.getElementsByClassName("status-button")
const arr = Array.from(proceedButtons);
console.log(arr[0]);
Old School
const arr = []
Array.prototype.forEach.call(proceedButtons, function(el) {
arr.push(el);
});
console.log(arr[0]);

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.

selectize.js and vue.js 2 ajax loaded optons

I'm using vuejs#2.3.3, selectize#0.12.4, vue2-selectize.
I have a pretty big form with a few select inputs.
All options are loaded by ajax into a one property, which is initialized with a demo data before being replaced by ajax data:
addTrackData : {
styles : [
{ id: 1, title: 'style 1' },
{ id: 2, title: 'style 3' },
{ id: 3, title: 'style 2' },
],
authors: [
{inn: '111', name: 'demo 1'},
{inn: '222', name: 'demo 2'},
{inn: '333', name: 'demo 3'}
]
....
},
And I've got 2 problems:
1) If I use settings in this way, options doesn't loads at all:
<selectize v-model="form.data.authors[i]['id']" :settings="selectize.authors"></selectize>
selectize: {
authors: {
valueField: 'inn',
labelField: 'name',
searchField: ['name', 'inn'],
options: this.addTrackData.authors // that doesn't works, but hard coded array works
}
}
Because of error Error in data(): "TypeError: Cannot read property 'authors' of undefined".
Both this.addTrackData.authors and addTrackData.authors makes this error.
But this way works:
<selectize v-model="form.data.authors[i]['id']"
:settings=" {
valueField: 'inn',
labelField: 'name',
searchField: ['name', 'inn'],
options: addTrackData.authors, // It works, but looks too ugly!
}" >
</selectize>
2) Options are not reactive - when ajax data comes, all selects elements still shows a demo data. And I have no idea how to update them all...
UPDATE
Second problem could be fixed with If Conditional and empty initial array:
<selectize v-if="addTrackData.authors.length" v-model="form.data.authors[i]['id']"
:settings=" {
valueField: 'inn',
labelField: 'name',
searchField: ['name', 'inn'],
options: addTrackData.authors, // It works, but looks too ugly!
}" >
</selectize>
addTrackData : {
styles : [],
authors: []
....
}
But the first problem still makes me cry
I just read the source code of vue2-selectize and noticed that it's watch code for options key is incorrect.
his code is this way:
watch: {
value() {
this.setValue()
},
options (value, old) {
if (this.$el.selectize && !equal(value, old)) {
this.$el.selectize.clearOptions()
this.$el.selectize.addOption(this.current)
this.$el.selectize.refreshOptions(false)
this.setValue()
}
}
},
while it should be this way to work:
watch: {
value() {
this.setValue()
},
options (value, old) {
if (this.$el.selectize && !equal(value, old)) {
this.$el.selectize.clear();
this.$el.selectize.clearOptions();
var vm = this;
this.$el.selectize.load(function(callback) {
callback(vm.current);
});
this.$el.selectize.refreshOptions(false);
this.setValue();
}
}
},
I just prepared a hacky way to make it working but I dont encourage you using it in production.
Here is the fiddle's link: https://jsfiddle.net/ahmadm/h8p97hm7/
I'll try to send a pull request to his creator as soon as possible but until that time, your solution is already the only possible solution.

Change event didn't work for selectfield?

i am getting struck with sencha touch select field change event. Usual change event is working fine. but in case option values like this,
{
xtype: 'selectfield',
label: 'Choose one',
options: [{text: 'First Option', value: 1},
{text: 'First Option', value: 2},
{text: 'Third Option', value: 3}],
listeners : {
change : function (selectField, newValue, oldValue)
{
console.log(newValue);
}
}
}
When this case values are different but display values are same, change event didn't work. Please help to finish this issue.
This is issue with Sencha. you can check this link
https://www.sencha.com/forum/showthread.php?304198-Select-field-not-firing-change-event-on-same-text-but-different-value.
But If You have a need to do this then you can do with this way, write this in launch function.
Ext.override(Ext.field.Input, {
setValue: function (newValue) {
var oldValue = this._value;
this.updateValue(this.applyValue(newValue));
newValue = this.getValue();
this.onChange(this, newValue, oldValue);
return this;
}
});

Categories