VueJS Array update bug - arrays

I have a JSFiddle below to explain my problem but basically I have an array called tiles which has a title. When the instance is created() I add a field to this array called active
I then output this array in an <li> element and loop through it outputting the title and active objects. My problem is as you can see in the fiddle when I run v-on:click="tile.active = true" nothing happens to the active state written in the <li> element
but if I run v-on:click="tile.title = 'test'" it seems to update the active object and the title object.
Its strange behaviour I can't seem to work out why. Does anyone have any ideas?
https://jsfiddle.net/jgb34dqo/
Thanks

It's to do with Vue not knowing about your properties, change your array to this:
tiles: [
{
title: 'tile one',
active: false
},
{
title: 'tile two',
active: false
},
{
title: 'tile three',
active: false
}
]
This allows Vue to know about the active property and in turn it knows to monitor that variable.
It's worth looking at this link about Vue Reactivity as it helps with understanding how and when data will change automagically.
If you must add the properties after
take a look at $set. It allows you to add props to an object that then get watched by vue. See this fiddle, notice the change:
this.tiles.forEach(function(tile) {
// Tell vue to add and monitor an `active` prop against the tile object
this.$set(tile, 'active', false);
}.bind(this))

Related

React - setState doesn't refresh component as expected

I might be experiencing either a bug, or I misunderstand something about general javascript syntax.
Using ServiceNow UI Builder, I'm trying to refresh the datasource of a specific data visualization component. Which requires me to use setState and send in an entire JSON blob.
The following works as expected:
api.setState('intAssignedDonut', {
"header": "Interactions assigned to one of my groups",
"datasource": [{
"isDatabaseView": false,
"allowRealTime": true,
"sourceType": "table",
"label": {
"message": "Interaction"
},
"tableOrViewName": "interaction",
"filterQuery": "active=true^assignment_groupDYNAMICd6435e965f510100a9ad2572f2b47744",
"id": "intAssigned",
"elm": {}
}],
"metric": [{
"dataSource": "intAssigned",
"id": "intAssignedMetric",
"aggregateFunction": "COUNT",
"numberFormat": {
"customFormat": false
},
"axisId": "primary"
}],
"groupBy": [{
"maxNumberOfGroups": "ALL",
"numberOfGroupsBasedOn": "NO_OF_GROUP_BASED_ON_PER_METRIC",
"showOthers": false,
"groupBy": [{
"dataSource": "intAssigned",
"groupByField": "state",
"isRange": false,
"isPaBucket": false
}]
}]
});
However, I only need to alter a few properties, not the whole thing.
So I thought I'd just clone the thing into a temp object, change what I need, then pass the cloned object back.
let clientState_intAssignedDonut = api.state.intAssignedDonut;
clientState_intAssignedDonut.header = 'Interactions assigned to one of my groups';
clientState_intAssignedDonut.datasource[0].filterQuery = 'active=true^assignment_groupDYNAMICd6435e965f510100a9ad2572f2b47744';
api.setState("intAssignedDonut", clientState_intAssignedDonut);
This seems to update the header properly, but the component doesn't refresh the datasource.
Even if I console.log api.state.intAssignedDonut it looks identical to the whole JSON blob.
EDIT: I also tried using spread operators, but I can't figure out how to target the datasource[0]
api.setState("intAssignedDonut", {
...api.state.intAssignedDonut,
header: "Interactions assigned to one of my groups",
datasource[0].filterQuery: "active=true^assignment_groupDYNAMICd6435e965f510100a9ad2572f2b47744"
});
Javascript objects are passed by reference values, and react state is immutable:
let clientState_intAssignedDonut = api.state.intAssignedDonut;
api.setState("intAssignedDonut", clientState_intAssignedDonut);
This is mutating the state directly, and React will ignore your update if the next state is equal to the previous state, which is determined by an Object.is comparison to check if both objects are of the same value, see docs
Your second attempt is heading to the right direction using spread operator:
Update method one: first copy the nested object using: JSON.parse(JSON.stringify(object)), or you can find other method in this question: What is the most efficient way to deep clone an object in JavaScript?
let copied = JSON.parse(JSON.stringify(api.state.intAssignedDonut)); // copy a nested object
copied.header = "Interactions assigned to one of my groups";
copied.datasource[0].filterQuery = "active=true^assignment_groupDYNAMICd6435e965f510100a9ad2572f2b47744";
setState("intAssignedDonut",copied);
Update method two:
setState("intAssignedDonut",{
...api.state.intAssignedDonut,
header: "Interactions assigned to one of my groups",
datasource: [{ ...state.datasource[0], filterQuery: "active=true^assignment_groupDYNAMICd6435e965f510100a9ad2572f2b47744" }]
});
Check out sandbox

load contents of array of objects into a vuetify combobox

I have this piece of code really confused me. I'm using typescript with vue (vuetify) and I'm still pretty new with typescript.
I have an array of objects that I want to load as items into a vuetify combobox.
Array =[
{
subject: 'science',
difficulty: 'medium'
}
{
subject: 'math',
difficulty: 'hard'
}]
with having the subject as the one visible on the dropdown and the difficulty will the the value hidden behind the combobox
i know it needs to look like this
items: [
{ text: 'science', value: 'medium' },
{ text: 'math', value: 'hard' }];
so i can load it on the v-combobox like this
<v-combobox :items="items" />
can anyone help me on how to achieve this? much appreciated!
I did not understand your issue but a typical combobox should be look like this:
(define selectedItem as an empty array in your data and call this.selectedItem.text)
<v-combobox
v-model="selectedItem"
:items="items"
item-value="value"
item-text="text"
:return-object="true"
label="Select an item.."
outlined
clearable
>
</v-combobox>
Yes for load the contents of array you set items props and also item-value et item-text props like #Aurora did. Because you an array of objects, and the component need to know what will be the value and the display field.

Set default option for `md-radio-group`

I have an extremely simple md-radio-group and I am having a tough time setting the default value. The group is using an object (which I am assuming is related to the problem).
Please reference my codepen example.
I am defaulting the md-radio-group to the 2nd option but the radio button is never selected.
Am I missing something?
Couple of changes here:
You are interpolating the value of the radio. Doing so is unncessary, and loses reference to the object in the array for which you are iterate. Change your value to ng-value="option".
In your controller, set your default option. Since array positions start at 0, for your second option, you'll use [1].
$scope.optionExample = $scope.options[1];
A simple way if you add another attribute to make default selection, like below
$scope.statusList = [{ id: "APN", status: "Approved", isChecked: true }, { id: "VIP", status: "Scheduled", isChecked: false }, ];
in HTML
<input type="checkbox" ng-model="item.isChecked" ng-repeat="item in statusList"/>
<label class="form-control" style="width:305px"> {{item.status}}  </label>

Angular - Filter based on nested array boolean

I'm trying to find a good way to filter on click, based on a boolean value that's within a nested array.
My current scope looks like the following
$scope.persons = [
{
firstName : 'Drew',
lastName : 'Minns',
views : [
{
name : 'View 1',
support : true
},
{
name : 'View 2',
support : false
}
],
},
{
firstName : 'Peter',
lastName : 'Parker',
views : [
{
name : 'View 1',
support : false
},
{
name : 'View 2',
support : false
}
],
}
];
I'm looking to add a filter that sorts based on the boolean value of each view object. The problem that I'm running into is that I can't access that value without iterating over every array. Doing that is making it tough to access each individual value without referencing the array number.
I want to hide the parent object based on whether or not the specific "view" object has a true or false in the support field.
Again, I'm looking to do this on click, so the idea is that you click a button for 'View 1' and only those parent objects with true value for support shows up. There will be multiple buttons for each "view" so I'm looking to provide the action of drilling down based on support for views.
Here's a plunkr http://plnkr.co/edit/ipi8vKEbxps2H89HTg00?p=preview
You can use Angular JS's "Filter" function to do this. Plunkr example, with the relevant change below
http://plnkr.co/edit/LHTpRqHbTxEAslY0rd5J?p=preview
<ul ng-repeat="view in person.views | filter:{ support: true }">
Edit: For what you want, I've slapped together a quick custom filter: http://plnkr.co/edit/LHTpRqHbTxEAslY0rd5J?p=preview

How do I programmatically set the hidden property for a Tab (button)

I have an Ext TabPanel, and I am trying to set the hidden property for one of the Tabs, programmatically. I am able to select the object and call methods such as disable() and enable() but so far have been unable to find a means by which I can manipulate the Tab's 'hidden' property.
The Tab is defined as
{
id: "view-task",
hidden: false,
title: "View"
}
and the code attempting to manipulate it
twin = ( Ext.getCmp('view-task'));
twin.disable();
The above call to disable works, so the component is being correctly selected but I do not know how to manipulate the hidden property.
Any assistance will be much appreciated.
N. Euzebe
Try this:
var tabs = Ext.createWidget('tabpanel', {
items: [{
itemId: 'home',
contentEl:'script',
title: 'Short Text',
closable: true
}]
});
tabs.child('#home').tab.hide();
You can find this code in examples on the API page
You haven't explained which version of ExtJS you're using. But in version 3.x you can do the following (I don't know, but it might also work in ExtJS 4.x):
var tabPanel = Ext.getCmp('myTabPanel');
var tabToHide = Ext.getCmp('myTab');
tabPanel.hideTabStripItem(tabToHide);
To show the tab again:
tabPanel.unhideTabStripItem(tabToHide);
Hope this helps you :)

Resources