Vue js props no data - javascript

I cant pass data to props in VueJS.
Here is my code:
const projects = [{ id: 1, name: 'First', img: "https://randomwordgenerator.com/img/picture-generator/53e0d7414855ac14f1dc8460962e33791c3ad6e04e5074417d2e72d2964cc6_640.jpg" },
{ id: 2, name: 'Second', img: "https://randomwordgenerator.com/img/picture-generator/paper-1100254_640.jpg" },
{ id: 3, name: 'Third', img: "https://randomwordgenerator.com/img/picture-generator/5fe2d4414352b10ff3d8992cc12c30771037dbf85254794075287cd69145_640.jpg" },
{ id: 4, name: 'Forth', img: "https://randomwordgenerator.com/img/picture-generator/5fe1d3414256b10ff3d8992cc12c30771037dbf8525478487c2f79d5924e_640.jpg" }
]
const Project = {
props: ['img', 'name'],
template: `
<div class="container projectbox">
<div class="textandimage"> Name: {{ projects.name }} </div>
</div>
`,
data() {
return {
projects
}
}
}
img:undefined
name:undefined
Please help.

Projects is a list (Array) of Objects. if you want to access an Object in the list, you need to reference its position. for example:
<div class="textandimage"> Name: {{ projects[0].name }} </div>
This will access the first Object in your list, and return the value of the key name
EDIT: for-loop
If you want to loop through the data to the template, do something like this:
<div v-for="(item, index) in projects" class="container projectbox" :key="index">
<div class="textandimage"> Name: {{ item.name }} </div>
</div>
Hope that makes more sense.

Related

Vue: How to get rid of duplicate content

I have an array of names using v-for I get the names, as you can see I have two v-fors where the content is duplicated in this example my content is small and doesn't look so scary in real life it can be much bigger and all the problem is that the content is repeated, I tried to apply slots but could not cope
Template
<template>
<div>
<div v-for="(item, index) in array" :key="index" class="names">
<div class="show-names">
<p>{{ item.name }}</p>
</div>
<div
v-for="(girlNames, index) in item.girlNames"
:key="index"
class="names"
>
<div class="show-names">
<p>{{ girlNames.name }}</p>
</div>
</div>
</div>
</div>
</template>
Script
<script>
export default {
data() {
return {
array: [
{ name: "Alex" },
{ name: "Jacob" },
{ name: "Robert" },
{
girlNames: [
{
name: "Anna",
},
{
name: "Kiwi",
},
{
name: "Ava",
},
],
},
],
};
},
};
</script>
Yes, this picture shows where the content is repeated
You can also see code example in codesandbox
The only problem I see here is bad data structure. In my opinion it should be an object with two fields, which seperate in your case boys and girls, and in this object should be actual data:
<script>
export default {
data() {
return {
names: {
boys: [
{ name: "Alex" },
{ name: "Jacob" },
{ name: "Robert" },
],
girls: [
{ name: "Anna" },
{ name: "Kiwi" },
{ name: "Ava" },
]
}
},
],
};
},
};
</script>
They your code in template will be like:
<template>
<div>
<div class="names">
<div v-for="(item, index) in name.boys" :key="index" class="show-names">
<p>{{ item.name }}</p>
</div>
<div v-for="(item, index) in name.girls" :key="index" class="show-names">
<p>{{ item.name }}</p>
</div>
</div>
</div>
</template>

How to properly iterate on array of objects in Vue/Nuxt

<template>
<div>
<h1>Hello World</h1>
<div>
<span :for="day in days">{{ day }} </span>
</div>
</div>
</template>
<script>
export default {
name: 'Hello',
data() {
return {
days: ['Mon', 'Tue', 'Wed', 'Thurs', 'Fri', 'Sat', 'Sun'],
}
},
}
</script>
I am not able to loop through days array. I am getting below error.
Error: [Vue warn]: Property or method "day" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property. See: https://v2.vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties.
Here is a similar question: Nuxt how to loop on an array and display the data properly with a v-for
And same as there, I do recommend generating some ids for properly handling of :key, otherwise you'll get an ESlint error.
<template>
<div>
<h1>Hello World</h1>
<div>
<span v-for="day in days" :key="day.id">
{{ day.name }}
</span>
</div>
</div>
</template>
<script>
export default {
name: 'Hello',
data() {
return {
days: [
{ id: 1, name: "Mon" },
{ id: 2, name: "Tue" },
{ id: 3, name: "Wed" },
{ id: 4, name: "Thurs" },
{ id: 5, name: "Fri" },
{ id: 6, name: "Sat" },
{ id: 7, name: "Sun" },
]
}
},
}
</script>
:key is essential, more info here: https://v2.vuejs.org/v2/style-guide/#Keyed-v-for-essential
Here a blog article explaining this: https://michaelnthiessen.com/understanding-the-key-attribute#dont-use-an-index-as-the-key
You should use v-for directive like :
<span v-for="day in days">{{ day }}</span>
the directives are prefixed by v- and they are bound by default to the component methods and properties

Live filter in custom select with input

I am trying to make a custom list filter on input using computed property. In one file I create a widget, in another I use it. Here is the code from the widget creation file:
<template>
<input value="Гарантийный случай"
v-model="searchText"
:class="{'w-autocomplete__input_completed': completed}"
ref="input"
#click="areOptionsVisible = !areOptionsVisible"/>
<div v-if="areOptionsVisible"
:style="{maxHeight: maxHeight, overflow: 'auto', zIndex: zIndex}"
class="w-autocomplete__items">
<div v-for="option in options" class="w-autocomplete__item_first" >
{{ option.name }}
<div v-for="item in option.children" class="w-autocomplete__item"
:class="{'w-autocomplete__item_active': currentIndex === item}"
#mouseenter="setActive(item)"
#keyup.up="changeCurrent('up', item)"
#keyup.down="changeCurrent('down', item)"
#click="doChoose(item)">
{{ item.name }}
</div>
</div>
</div>
</template>
<script>
export default {
name: 'dropdown',
props: {
placeholder: {
type: String,
required: false,
default: '',
},
options: {
type: Array,
default(){
return []
}
},
},
data: function () {
return {
counter: 0,
currentIndex: null,
completed: false,
chosenItem: null,
areOptionsVisible: false,
searchText: '',
data: [],
}
},
computed: {
options(){
return this.props.options.filter(elem => {
return elem.name.toLowerCase().includes(this.searchText.toLowerCase());
});
},
},
.......
}
</script>
This is how I pass the array to this list in another file:
<template>
........
<div class="complaint-form__line-item">
<div class="form-group">
<label>Гарантийный случай</label>
<dropdown :options="options" />
</div>
</div>
........
</template>
<script>
........
export default {
name: 'complaint-form',
components: {LockedImport, UploadFiles, CarNumberInput, Autocomplete, Dropdown},
props: {
......
}
},
data() {
const complaint = new Complaint();
return {
........
options: [
{name: 'Выход детали из строя в процессе эксплуатации', value: null,
children: [{name: 'Увеличение зазора, люфт (дробь/стуки)', value: 53},
{name: 'Обрыв детали', value: 54}]},
{name: 'Поломка при установке', value: null},
{name: 'Брак до установки', value: null,
children: [{name: 'Недокомплект', value: 55},
{name: 'Заводской брак (замятия, отсутствие резьбы, пробой пыльника и т.д.)',
value: 56}]},
],
}
},
Tell me please why computed doesn't work? Only I add computed and the list is not displayed at all when clicking on the field, but should. That is, it breaks down completely. I want to be filtered when entering text in input
Vue.js cannot have more than one element inside a <template> tag, so I would suggest that you enclose the whole code of the dropdown component within a <div> tag or something of the sort.
Also, and this is just a comment, I would suggest that you use the focus event for the input because with click it will still be showing even if you aren't focusing on the input.

In ReactJS, how can I best organize my code when iterating over non-shallow data structures

I'm using React and I have the following data structure:
[
{
key: 'test'
data: [
{
id: 1,
name: 'test name',
desc: 'aaaaaaaaa'
},
{
id: 2,
name: 'test name2',
desc: 'aaaaaaaaa'
},
{
id: 3,
name: 'test name3',
desc: 'aaaaaaaaa'
}
]
},
{
key: 'test2'
data: [
{
id: 5,
name: 'test name5',
desc: 'aaaaaaaaa'
},
{
id: 5,
name: 'test name2',
desc: 'aaaaaaaaa'
},
{
id: 6,
name: 'test name6',
desc: 'aaaaaaaaa'
}
]
}
]
I'm looking for a better way of fetching data from such a structure. The thing is that is should be one ul list with li items inside.
I have such a structure for this:
<div className='wrapper'}>
{tabInfo.map(({key, data}) => {
return (
<div className='tab-list' key={key}>
<h4>{key}</h4>
<ul>
{data.map(({id, name, desc}) => {
return (
<li key={id}>
<span className='name'>
{name}
</span>
<span className="desc">{desc}</span>
</li>
)
})}
</ul>
</div>
)
})}
</div>
What is the better way of fetching the data in such a case? I think map inside map isn't good idea.
I believe this will do it, though I haven't tested this to be sure. You can move this to a separate component which can then be used as part of the map:
const ListItem = ({ id, name, desc }) => (
<li key={id}>
<span className='name'>
{name}
</span>
<span className="desc">
{desc}
</span>
</li>
);
<div className='wrapper'}>
{tabInfo.map(({key, data}) => {
return (
<div className='tab-list' key={key}>
<h4>{key}</h4>
<ul>
{data.map(dataItem => <ListItem {...dataItem} />)}
</ul>
</div>
)
})}
</div>
I may have missed something here, so if there are any problems, I'd be happy to know about the,m so I can fix this up

How do I get the real index of this user in my array?

I'm getting my example from Vue JS docs
If I have a v-for that's filtered, how do I get the real index of this user in my array? Not the index of the current iteration, but the index of the item from the array.
<div id="filter-by-example">
<ul>
<li v-for="user in users | filterBy 'Jim' in 'name'">
{{ user.name }}
{{ $index }} <!--I want Jim's index to be 3, not 0-->
</li>
</ul>
</div>
Vue JS:
new Vue({
el: '#filter-by-example',
data: {
users: [
{ name: 'Bruce' },
{ name: 'Chuck' },
{ name: 'Jackie' },
{ name: 'Jim' },
]
}
})
This should do it:
new Vue({
el: '#filter-by-example',
data: {
users: [
{ name: 'Bruce' },
{ name: 'Chuck' },
{ name: 'Jackie' },
{ name: 'Jim' },
]
},
methods : {
getIndexOfItem: function(arr, item) {
return arr.indexOf(item);
}
}
});
<script src="https://unpkg.com/vue#next/dist/vue.js"></script>
<div id="filter-by-example">
<ul>
<li v-for="user in users">
{{getIndexOfItem(users, user)}} - {{user.name}}
</li>
</ul>
</div>
Added a getIndexOfItem method into the methods collection and in the v-for passed in the array and item then returned the item index, this seems complex but most other implementations didn't seem to work work.
Edit 2
I removed the function inside the methods collection.
<li v-for="(user, index) in users | filterBy 'Jim' in 'name'">
https://jsbin.com/misagagewo/edit?output
As far as I know you can't. You can do something like this though.
<div id="filter-by-example">
<ul>
<li v-for="user in users | filterBy 'Jim' in 'name'">
{{ user.name }}
{{ user._index }}
</li>
</ul>
</div>
JS:
function fixupObjArray(arr) {
arr.forEach((e,i) => e._index = i);
return arr;
}
new Vue({
el: '#filter-by-example',
data: {
users: fixupObjArray( [
{ name: 'Bruce' },
{ name: 'Chuck' },
{ name: 'Jackie' },
{ name: 'Jim' },
] )
}
})

Categories