How to pass an object to a web component generated width Vue? - javascript

My component has to render an object to fill the content. When I am working in the Vue project, I have not problem to pass this object with
<my-compnent :card="card"></my-component>
But when I tried to use the built component, it doesn't read "MyCard" as an object, ir reads as a string... please, some help
I have tried in the same way that vue, using :card but it doesn´t work, if I only use card="card" it get access to the component but without the object
My code:
<script>
card =
{
name: 'card',
graphic: 'https://static.anychart.com/images/gallery/v8/line-charts-line-chart.png',
subtitle: 'about this card',
info: 'this is a test content card',
selector1: [
{ name: 'opt 1' },
{ name: 'opt 2' },
{ name: 'opt 3' }
],
selector2: [
{ name: 'opt A' },
{ name: 'opt B' },
{ name: 'opt C' }
]
}
</script>
<script src="https://unpkg.com/vue"></script>
<body>
<my-component card="card"></card>
</body>
And the error:
[Vue warn]: Invalid prop: type check failed for prop "card". Expected Object, got String with value "card".
Also I have tried
<my-component :card="card"></card>
but this only works in a vue project, not in exported web-components. It gives this error:
[Vue warn]: Error in render: "TypeError: can't access property "name", _vm.card is undefined"

card="card" will pass the string 'card' as value to the card attribute. If you want to pass a JS object tp an exported web component outside Vue, then you'll have to do it in JS itself.
<script>
const card =
{
name: 'card',
graphic: 'https://static.anychart.com/images/gallery/v8/line-charts-line-chart.png',
subtitle: 'about this card',
info: 'this is a test content card',
selector1: [
{ name: 'opt 1' },
{ name: 'opt 2' },
{ name: 'opt 3' }
],
selector2: [
{ name: 'opt A' },
{ name: 'opt B' },
{ name: 'opt C' }
]
}
let comp = document.querySelector('my-component')
comp.card = card
</script>
<body>
<my-component card="card"></card>
</body>
You can use v-bind:card or simply ':card' only if you're working inside vue project, in which case you don't need to use exported component. But in this case the object card needs to be passed to the data property of your Vue instance, otherwise Vue can't find it. This is why you get the error.
<script>
const app = new Vue({
el: '#app',
data: {
card,
},
}
</script>

Related

toggle tabs with vue props not working - Quasar

I have quasar tabs that are being rendered in v-for loop.
Problem is that when I provide array as prop from parent, then my tabs stop working to toggle whereas it works with local array.
<div v-for="test in tests">
<q-tabs
v-model="test.status"
align="justify"
>
<q-tab
v-for="(tab, tabIndex) in tabs"
:key="tabIndex"
:name="tab.value"
>
{{ tab.name }}
</q-tab>
</q-tabs>
</div>
<script>
export default {
props: ['tests']
data (){
return {
tabs: [
{
name: 'Required',
value: 'required'
},
{
name: 'Not Required',
value: 'not-required'
}
]
}
}
Tests Data
[
{
id: "test 1"
name: 'TEST 1'
status: 'required'
},
{
id: "test 2"
name: 'TEST 2'
status: 'not-required'
}
]
Expected result
Toggle of tabs must work when component is provided with props data to iterate.

React state object attribute is getting set as undefined

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]);

How can I modify and extend properties of an object located in useState Array?

I'm a react.js beginner, searching for methods to alter my data structure. For example, I want to push new objects into the children-array or remove them by key.
What is the appropriate way to do that?
const [treeData, setTreeData] = useState([
{
title: "parent 1",
key: "0-0",
icon: <UserAddOutlined />,
children: [
{
title: "parent 1-0",
key: "0-0-0",
icon: <UserAddOutlined />,
children: [
{
title: "leaf",
key: "0-0-0-0",
icon: <UserAddOutlined />,
},
{
title: "leaf",
key: "0-0-0-1",
icon: <UserAddOutlined />,
},
],
},
{
title: "parent 1-1",
key: "0-0-1",
icon: <UserAddOutlined />,
children: [
{
title: "sss",
key: "0-0-1-0",
icon: <UserAddOutlined />,
},
],
},
],
},
]);
So you should not update the state directly. It is not allowed.
Maybe where you are receiving data from, suppose via api and the data is response.payload.data etc.
So in your case use the setTreeData(response.payload.data) method to add stuff in it.
Now if you want to update certain value (remove or update using index etc). Obviously you will have to have index somehow.
So for deleting say you will have some click and against that a handler for it
removeItem(e) {
item_to_remove = e.target..... etc // to get the item's reference for matching
setTreeData(treeData.filter(items => item.<someproperty> != item_to_remove))
// In your case could also be targetting children maybe
// setTreeData(treeData.Children.filter(items => item.<someproperty> != item_to_remove))
}
I would say maybe handle childrens' array inside another useState variable (childrenTreeData maybe). But you will have to look it's feasibility too. Just an idea after seeing your data
JUST for INFO
This is something similar I did for updating prices inside each cards in my project
const getCurrentPrice = useCallback(() => { // <======= maybe you do not need this
const updatedTilesData = tilesData.map((tile: any) => {
return {
...tile, // <======= get everything here and then update the price below for item
currentPrice: calculateDNCurrentPrice(
tile.startingPrice,
tile.dnTimestamp
),
};
});
setTilesData(updatedTilesData);
}, [tilesData]);

Language object prop to pass in the react component

I have created a demo using a tutorial that i have found.
This is the demo => https://codesandbox.io/s/strange-monad-otv0g?file=/src/language.js
In App.js the sidebar is receiving the array of objects as props, it all works fine
const sidebaritems = [
{
name: "first",
label: "First",
items: [
{ name: "sublink2", label: "SubLink 1" },
{ name: "sublink3", label: "SubLink 2" }
]
},
"divider",
{
name: "second",
label: "Second",
items: [
{ name: "subLink 1", label: "SubLink 1" },
{ name: "subLink 2", label: "SubLink 2" }
]
},
"divider",
{
name: "third",
label: "Third"
}
];
<SideBar items={sidebaritems} />
I want now to use an external data language file that i import where i have other translations and also sidebaritems to pass, so i have created language.js and imported in the App.js
import dataForTexts from "./language.js";
My question is, how can i pass from language.js the same sidebaritems in my sidebar component in app.js
You need a named import to import your dataForTexts . So change your import statement as
import { dataForTexts } from "./language.js";
Now pass the sidebaritems as
<SideBar items={dataForTexts.sidebaritems} />
As I understand it you need this. As items, you just need to pass your data from language.js (dataForTexts)

Two Way Link Using Normalizr

I have a list of regions, which I get from an API. In this list, there are multiple buildings. This will look like this in JS:
const regions = [
{
guid: 'REGION1-GUID',
name: 'Region 1',
buildings: [
{
guid: 'REGION1-BUILDING1-GUID',
name: 'Region 1 Building 1'
},
{
guid: 'REGION1-BUILDING2-GUID',
name: 'Region 1 Building 2'
}
]
},
{
guid: 'REGION2-GUID',
name: 'Region 2',
buildings: [
{
guid: 'REGION2-BUILDING1-GUID',
name: 'Region 2 Building 1'
},
{
guid: 'REGION2-BUIDLING2-GUID',
name: 'Region 2 Building 2'
}
]
}
];
Now I want to normalize this JS Object using normalizr. What I want to do later is to get the region from a building.
So I tried to do the following:
// Define the buildings schema
const building = new schema.Entity('building', {}, { idAttribute: 'guid' });
// Define the regions schema
const region = new schema.Entity(
'regions',
{
buildings: [building]
},
{ idAttribute: 'guid' }
);
const regionList = [region];
const normalizeData = () => {
const normalizedData = normalize(data, regionList);
This does normalize my object, the normalizedData is like this:
{
"entities":{
"building":{
"REGION1-BUILDING1-GUID":{
"guid":"REGION1-BUILDING1-GUID",
"name":"Region 1 Building 1"
},
"REGION1-BUILDING2-GUID":{
"guid":"REGION1-BUILDING2-GUID",
"name":"Region 1 Building 2"
},
"REGION2-BUILDING1-GUID":{
"guid":"REGION2-BUILDING1-GUID",
"name":"Region 2 Building 1"
},
"REGION2-BUIDLING2-GUID":{
"guid":"REGION2-BUIDLING2-GUID",
"name":"Region 2 Building 2"
}
},
"regions":{
"REGION1-GUID":{
"guid":"REGION1-GUID",
"name":"Region 1",
"buildings":[
"REGION1-BUILDING1-GUID",
"REGION1-BUILDING2-GUID"
]
},
"REGION2-GUID":{
"guid":"REGION2-GUID",
"name":"Region 2",
"buildings":[
"REGION2-BUILDING1-GUID",
"REGION2-BUIDLING2-GUID"
]
}
}
},
"result":[
"REGION1-GUID",
"REGION2-GUID"
]
}
But to get the Region of a building i need to iterate over every region and check if the building is contained in the list. I will not get any added value trough the normalization.
It would be perfect if I am able to link in both direction. Every region entitiy has a list of building guids and every building has one region guid.
Is there any way to archieve this in normalizr? What would be the best approach?
Thank you for your help.
I tried some things and found a working solution. I don't know if there is any better approach, but it's very clean code and it's working.
I just had to change the definition of the building entity to:
// Define buildings schema
const building = new schema.Entity(
'building',
{},
{
idAttribute: 'guid',
processStrategy: (entity, parent) => ({ ...entity, regionGuid: parent.guid })
}
);
This will add the property "regionGuid" to the building which holds the guid from the region.

Categories