How can I get a value of a variable by reference? - javascript

I have an array called tags which contain names for restauants. I want to use this in the for loop in the GMapMarker to go to retrieve data from the array that has the name.
let tags[] = {name: 'mcdonalds', id: '1'}, {name: 'burger king', id: '2'}, {name: 'subway', id: '3'}
mcdonalds: [{icon: 'mdi-mcdonalds', position: '2323, 4234'}, {icon: 'mdi-mcdonalds', position: '77654, 34554'} ]
burgerking: [{icon: 'mdi-burgerking', position: '756656, 43243'}, {icon: 'mdi-burgerking', position: '8744, 36774'} ]
subway: [{icon: 'mdi-subway', position: '2154, 65654'}, {icon: 'mdi-subway', position: '6453, 3562'} ]
<div v-for="tag in tags.name" :key="tag">
<GmapMarker
v-for="(restaurant, index) in **tag**"
:key="index"
:position="restaurant.position"
:icon="restaurant.icon"
#click="openMenu(restaurant)"
/>
</div>
I tried using ${{restaurant}}. But it seems to not retrieve data from the array.

Here's an example using your data. tags and restaurants are exposed to the template via computed properties.
NOTES:
I altered "burger king" to be "burgerking" so the match would work.
I changed the example template to use lists instead of GmapMarker so it could run in my environment.
<template>
<div>
<div v-for="tag in tags" :key="tag.id">
<ul>
<li
v-for="(restaurant, index) in restaurants[tag.name]"
:key="index"
:position="restaurant.position"
:icon="restaurant.icon"
#click="openMenu(restaurant)"
>
{{ restaurant.position }}
</li>
</ul>
</div>
</div>
</template>
<script>
export default {
computed: {
tags() {
return [
{ name: 'mcdonalds', id: '1' },
{ name: 'burgerking', id: '2' },
{ name: 'subway', id: '3' },
];
},
restaurants() {
return {
mcdonalds: [
{ icon: 'mdi-mcdonalds', position: '2323, 4234' },
{ icon: 'mdi-mcdonalds', position: '77654, 34554' },
],
burgerking: [
{ icon: 'mdi-burgerking', position: '756656, 43243' },
{ icon: 'mdi-burgerking', position: '8744, 36774' },
],
subway: [
{ icon: 'mdi-subway', position: '2154, 65654' },
{ icon: 'mdi-subway', position: '6453, 3562' },
],
};
},
},
};
</script>
If your computed values are read from Vuex state, your script section may look something like:
<script>
import { mapState } from 'vuex';
export default {
computed: {
...mapState(['tags', 'restaurants']),
},
};
</script>

Related

How to highlight active menu item with Typescript and Vue.js 3?

I have a menu and would like to highlight the currently active menu item.
I think I should write in the first template the following: v-if(selected) and some function maybe.
<template>
<MenuTreeView #selected='collapsedMenuSelected' :items='filteredFirstLevelNavigation' :filter="false"/>
</template>
MenuTreeView:
<template>
<Tree :value="items" filterPlaceholder="Suche" :expandedKeys="expandedKeys" filterMode="lenient" :filter="filter"
selectionMode="single" #nodeSelect="onNodeSelect"></Tree>
</template>
In such cases, you need to store the id of the active element in the data of the parent component. This can be done by saving the id when selecting one of the rows.
Parent
<template>
<div class="menu">
<MenuItem
v-for="row in rows"
:active-id="activeId"
:key="row.id"
#select="handleSelect"
/>
</div>
</template>
<script>
import MenuItem from "./MenuItem";
export default {
name: "TheMenu",
components: {
MenuItem,
},
data() {
return {
activeId: null,
rows: [
{
id: 1,
label: "First",
},
{
id: 2,
label: "Second",
},
{
id: 3,
label: "Third",
},
],
};
},
methods: {
handleSelect(id) {
this.activeId = id;
},
},
};
</script>
Child
<template>
<div
class="menu-item"
:class="{
'menu-item_active': activeId === row.id,
}"
#click="handleSelect"
>
{{ row.label }}
</div>
</template>
<script>
export default {
name: "MenuItem",
props: {
row: {
type: Object,
required: true,
},
activeId: {
type: Number,
required: true,
},
},
methods: {
handleSelect() {
this.$emit("select", this.row.id);
},
},
};
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.menu-item {
/* your styles */
display: flex;
width: 100%;
}
.menu-item_active {
background-color: red;
}
</style>

filtering items with multiple filters using vue js

I'm learning Vue JS and trying to use multiple filters to filter multiple products.
So, I have an example of 6 filters, product 1 to product 6. And I also have 6 products with different categories. I've coded as below, but when I try to click button filter, to filter the product, it doesn't work. I've tried various ways still not working.
Can anyone help me explain it and deal with this problem?
new Vue({
el: '#app',
data () {
return {
categories:[
{
category_title: 'Product 1',
category_name: "product-1"
},
{
category_title: 'Product 2',
category_name: "product-2"
},
{
category_title: 'Product 3',
category_name: "product-3"
},
{
category_title: 'Product 4',
category_name: "product-4"
},
{
category_title: 'Product 5',
category_name: "product-5"
},
{
category_title: 'Product 6',
category_name: "product-6"
},
],
productItems: [
{
name: 'Pro1',
category: 'product-1'
},
{
name: 'Pro2',
category: 'product-2'
},
{
name: 'Pro3',
category: 'product-3'
},
{
name: 'Pro4',
category: 'product-4'
},
{
name: 'Pro5',
category: 'product-5'
},
{
name: 'Pro6',
category: 'product-6'
},
],
}
},
computed: {
productFilter(){
return this.productItems;
},
filterProduct(){
return this.productItems.filter((product) => product.category == this.categories.category_name)
}
}
})
.product-items span{
margin: 20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css" integrity="sha512-iBBXm8fW90+nuLcSKlbmrPcLa0OT92xO1BIsZ+ywDWZCvqsWgccV3gFoRBv0z+8dLJgyAHIhR35VZc2oM/gI1w==" crossorigin="anonymous" referrerpolicy="no-referrer" />
<div id="app">
<div class="product-filter">
<button #click="filterProduct" v-for="cat in categories" :key="cat.id">
{{ cat.category_title }}
</button>
</div>
<div class="product-items">
<span v-for="product in productFilter" :key="product.id">{{ product.name }}</span>
</div>
</div>
Move the filterProduct from the computed properties to methods. Generally actions are to be placed inside methods and the computed properties holds the data which changes with respect to the dependent values used inside the defenition of that particular computed property.
Here I have created a data property called activeCategory which is being set when the user clicks any one of the category button. The productFilter computed property makes use of activeCategory data property. So when ever the data property activeCategory gets updated from the function filterProduct, the productFilter computed property automatically retrns new set of products.
new Vue({
el: '#app',
data() {
return {
categories: [
{
category_title: 'Product 1',
category_name: "product-1"
},
{
category_title: 'Product 2',
category_name: "product-2"
},
{
category_title: 'Product 3',
category_name: "product-3"
},
{
category_title: 'Product 4',
category_name: "product-4"
},
{
category_title: 'Product 5',
category_name: "product-5"
},
{
category_title: 'Product 6',
category_name: "product-6"
},
],
productItems: [
{
name: 'Pro1',
category: 'product-1'
},
{
name: 'Pro2',
category: 'product-2'
},
{
name: 'Pro3',
category: 'product-3'
},
{
name: 'Pro4',
category: 'product-4'
},
{
name: 'Pro5',
category: 'product-5'
},
{
name: 'Pro6',
category: 'product-6'
},
],
activeCategory: null,
}
},
methods: {
filterProduct(category) {
this.activeCategory = category;
}
},
computed: {
productFilter() {
return this.activeCategory ?
this.productItems.filter((product) => product.category == this.activeCategory.category_name) :
this.productItems;
},
}
})
.product-items span {
margin: 20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css"
integrity="sha512-iBBXm8fW90+nuLcSKlbmrPcLa0OT92xO1BIsZ+ywDWZCvqsWgccV3gFoRBv0z+8dLJgyAHIhR35VZc2oM/gI1w=="
crossorigin="anonymous" referrerpolicy="no-referrer" />
<div id="app">
<div class="product-filter">
<button #click="filterProduct(cat)" v-for="cat in categories" :key="cat.id">
{{ cat.category_title }}
</button>
</div>
<div class="product-items">
<span v-for="product in productFilter" :key="product.id">{{ product.name }}</span>
</div>
</div>
The method filterProduct should be defined inside methods option and add filtered property that will take the filtered products when you click the button, this click button runs the method that takes the current category as parameter :
new Vue({
el: '#app',
data() {
return {
categories: [{
category_title: 'Product 1',
category_name: "product-1"
},
{
category_title: 'Product 2',
category_name: "product-2"
},
{
category_title: 'Product 3',
category_name: "product-3"
},
{
category_title: 'Product 4',
category_name: "product-4"
},
{
category_title: 'Product 5',
category_name: "product-5"
},
{
category_title: 'Product 6',
category_name: "product-6"
},
],
productItems: [{
name: 'Pro1',
category: 'product-1'
},
{
name: 'Pro2',
category: 'product-2'
},
{
name: 'Pro3',
category: 'product-3'
},
{
name: 'Pro4',
category: 'product-4'
},
{
name: 'Pro5',
category: 'product-5'
},
{
name: 'Pro6',
category: 'product-6'
},
],
filtered: []
}
},
computed: {
productFilter() {
return this.productItems;
},
},
methods: {
filterProduct(cat) {
this.filtered = this.productItems.filter((product) => product.category == cat.category_name)
}
}
})
.product-items span {
margin: 20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css" integrity="sha512-iBBXm8fW90+nuLcSKlbmrPcLa0OT92xO1BIsZ+ywDWZCvqsWgccV3gFoRBv0z+8dLJgyAHIhR35VZc2oM/gI1w==" crossorigin="anonymous" referrerpolicy="no-referrer"
/>
<div id="app">
<div class="product-filter">
<button #click="filterProduct(cat)" v-for="cat in categories" :key="cat.id">
{{ cat.category_title }}
</button>
</div>
<div class="product-items">
<span v-for="product in filtered" :key="product.id">{{ product.name }}</span>
</div>
<pre>
<pre>
{{filtered}}
</pre>
</div>

Vue.js (vuex). Computed property returns undefined when reloading the page. (Hard coded array of objects data in vuex)

I am building a shoe shop with Vue and the problem is that I am getting undefined when reloading the page when I am trying to access a getter through computed property on the ShoeDetail component.I am storing some hard coded array of objects data in the vuex state. In the Shoe component I am looping through the data with v-for and outputting in the Men view, that is working for me, all avaliable shoes are displayed. When a user clicks on the shoe image a new route is loaded for each shoe with further details for that shoe which got clicked. I am using the id for dynamic routing. Now i have a getter in vuex
getProductById: (state) => (id) => {
return state.sneakers.find((sneaker) => sneaker.productId === id);
},
then I access it through a computed property:
product() {
return this.$store.getters.getProductById(this.$route.params.id);
},
that works fine and I can output the data stored in vuex state by interpolitaion like:
{{product.brand}}
When I reload the page I get this error:
**[Vue warn]: Error in render: "TypeError: Cannot read property 'brand' of undefined"
found in
---> <Detail> at src/components/ShoeDetail.vue
<App> at src/App.vue
<Root>**
I have tried to use v-if="product" but since im not making an API call this shouldn't be relevant.
I have also installed the createPersistedState but it still doesn't work. I am really stuck here and a hint on why im getting undefined on page reload would be appreciated
My vuex:
import Vue from 'vue';
import Vuex from 'vuex';
import createPersistedState from 'vuex-persistedstate';
Vue.use(Vuex);
export default new Vuex.Store({
plugins: [
createPersistedState({
key: 'keyname',
storage: window.localStorage,
}),
],
state: {
sneakers: [
{
productId: 1,
productno: 1234,
brand: 'nike',
gender: 'men',
size: 5,
price: 150,
image: require('#/assets/images/nike-air-zoom.jpg'),
},
{
productId: 2,
productno: 1235,
brand: 'adidas',
gender: 'men',
size: 10,
price: 140,
image: require('#/assets/images/sneakers.jpg'),
},
{
productId: 3,
productno: 1236,
brand: 'adidas',
gender: 'men',
size: 10,
price: 130,
image: require('#/assets/images/man-holding-nikes.jpg'),
},
{
productId: 4,
productno: 1237,
brand: 'nike',
gender: 'men',
size: 5,
price: 120,
image: require('#/assets/images/nike-air-zoom.jpg'),
},
{
productId: 5,
productno: 1238,
brand: 'adidas',
gender: 'men',
size: 10,
price: 110,
image: require('#/assets/images/sneakers.jpg'),
},
{
productId: 6,
productno: 1239,
brand: 'adidas',
size: 10,
price: 100,
image: require('#/assets/images/man-holding-nikes.jpg'),
},
],
},
getters: {
getProducts: (state) => {
return state.sneakers;
},
getProductById: (state) => (id) => {
return state.sneakers.find((sneaker) => sneaker.productId === id);
},
},
});
The Shoe component:
<template>
<div class="shoe-container">
<div class="shoe-card" v-for="element in products" :key="element.id">
<router-link
:to="{ name: 'ShoeDetail', params: { id: element.productId } }"
><img :src="element.image" tag="img" alt="" class="shoe-card__image"
/></router-link>
<p class="shoe-card__model">{{ element.brand }}</p>
<p class="shoe-card__price">{{ element.price }} $</p>
</div>
</div>
</template>
<script>
export default {
computed: {
products() {
return this.$store.getters.getProducts;
},
product() {
return this.$store.getters.getProductById(this.$route.params.id);
},
},
};
</script>
<style lang="scss" scoped>
#import '../sass/components/shoe';
</style>
The men view:
<template>
<div>
<navbar></navbar>
<sub-nav></sub-nav>
<filter-section></filter-section>
<section class="shoes">
<shoe></shoe>
</section>
</div>
</template>
<script>
import Navbar from "../components/Navbar.vue";
import SubNav from "../components/SubNav.vue";
import FilterSection from "../components/FilterSection.vue";
import Shoe from "../components/Shoe.vue";
export default {
components: {
Navbar,
SubNav,
FilterSection,
Shoe
}
};
</script>
<style lang="scss" scoped>
#import "../sass/views/men";
</style>
The ShoeDetail component:
<template>
<div class="details">
<h1>This is details</h1>
<h2>{{ product.brand }}</h2>
</div>
</template>
<script>
export default {
name: 'detail',
computed: {
product() {
return this.$store.getters.getProductById(this.$route.params.id);
},
},
};
</script>
<style lang="scss" scoped>
#import '../sass/components/shoeDetail';
</style>
Thanks for the answer I was able to fix it by adding parseInt in the computed property of ShoeDetail.
computed: {
product() {
return this.$store.getters.getProductById(
parseInt(this.$route.params.id)
);
},
}
Do this in the ShoeDetail component:
data: () => {
data: '',
},
methods: {
getProduct () {
this.product = this.$store.getters.getProductById(this.$route.params.id);
},
},
mounted () {
this.getProduct();
}
and it should work :)

Dropdown menu get object JSON

I want get object name from dropdown menu when item is selected. how to get object from event itemSelect? Thanks for attention.
Dropdown menu pic
XML code:
<core:FragmentDefinition
xmlns="sap.m"
xmlns:core="sap.ui.core"
xmlns:u="sap.ui.unified">
<u:Menu items="{kepesertaanmodel>/}" id="menuEventingKepesertaan"
itemSelect="handleMenuItemPressKepesertaan">
<u:MenuItem
text="{kepesertaanmodel>name}"
icon="{kepesertaanmodel>icon}">
<u:Menu items="{kepesertaanmodel>sub/}" id="submenuEventingKepesertaan"
itemSelect="handleSubMenuItemPressKepesertaan">
<u:MenuItem
text="{kepesertaanmodel>name}"
icon="{kepesertaanmodel>icon}"/>
</u:Menu>
</u:MenuItem>
</u:Menu>
</core:FragmentDefinition>
Javascript code:
handleMenuItemPressKepesertaan: function(oEvent) {
alert(oEvent.getSource().getItems().getBindingContext().getObject().name);
}
JSON structure:
dropdownMenu: {
kepesertaan:[
{
name: "Menu1",
icon: "sap-icon://crop",
sub: [
{
name: "Submenu1-1",
icon: "sap-icon://create-session"
},
{
name: "Submenu1-2",
icon: "sap-icon://create-form"
}
]
},
{
name: "Menu2",
icon: "sap-icon://detail-view",
sub: [
{
name: "Submenu2-1",
icon: "sap-icon://add-activity"
},
{
name: "Submenu2-2",
icon: "sap-icon://action"
}
]
}
]
}
How to fix this problem?
Does this help:
oEvent.getParameter("item").getBinding("text").getValue("name")
You can also have a look at this snippet

NG-Repeat to produce a list with dynamic classes

I'm trying to print as an li any item that matches the index of the first loop.
For example: first loop makes li's classed as cat1_li, 2nd one as cat2_li, 3rd one as cat3_li
However the closest I can get prints them all out in separate lists.
Having real trouble getting my head around using ng-repeats inside other ng-repeats and can't seem to find where the issue is. I can see why it is printing multiple lists, but not how to remedy this behaviour.
Would anyone be willing to take a look?
HTML:
<div>
<ul class="tasks" ng-repeat="cat in taskCategories.categories">
{{ cat }}
<li ng-repeat="tasks in tasklist.tasks | orderBy:'category' | filter: {category: cat}" class="cat{{ index + 1 }}_li">
<span>
<span class="panel_title">
{{ tasks.title }}
</span>
</span>
</li>
</ul>
</div
Object:
app.controller('MainController', ['$scope', function($scope) {
$scope.taskCategories = {
categories: [
'work',
'chores',
'learning',
'lifting'
]
};
$scope.tasklist = {
tasks: [{
title: 'Email Gregory',
category: 'work'
}, {
title: 'Clean the Kitchen',
category: 'chores'
}, {
title: 'AngularJS',
category: 'learning'
}, {
title: 'Hose Car',
category: 'chores'
}, {
title: 'Email Jethro',
category: 'work'
}, {
title: '400 lbs',
category: 'lifting'
}
]
};
}]);
You can use $parent.$index if you're trying to use the Category's index inside the nested ng-repeat:
var app = angular.module('app', []);
app.controller('MainController', ['$scope',
function($scope) {
$scope.taskCategories = {
categories: [
'work',
'chores',
'learning',
'lifting'
]
};
$scope.tasklist = {
tasks: [{
title: 'Email Gregory',
category: 'work'
}, {
title: 'Clean the Kitchen',
category: 'chores'
}, {
title: 'AngularJS',
category: 'learning'
}, {
title: 'Hose Car',
category: 'chores'
}, {
title: 'Email Jethro',
category: 'work'
}, {
title: '400 lbs',
category: 'lifting'
}]
};
}
]);
.cat1_li {
background-color: yellow;
}
.cat2_li {
background-color: cyan;
}
.cat3_li {
background-color: pink;
}
.cat4_li {
background-color: lime;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="MainController">
<ul class="tasks" ng-repeat="cat in taskCategories.categories">
{{ cat }}
<li ng-repeat="tasks in tasklist.tasks | orderBy:'category' | filter: {category: cat}" class="cat{{ $parent.$index + 1 }}_li">
<span>
<span class="panel_title">
{{ tasks.title }}
</span>
</span>
</li>
</ul>
</div>
UPDATE
After reading your comment in the question, you don't need two ng-repeat at all:
var app = angular.module('app', []);
app.controller('MainController', ['$scope',
function($scope) {
$scope.taskCategories = {
categories: [
'work',
'chores',
'learning',
'lifting'
]
};
$scope.tasklist = {
tasks: [{
title: 'Email Gregory',
category: 'work'
}, {
title: 'Clean the Kitchen',
category: 'chores'
}, {
title: 'AngularJS',
category: 'learning'
}, {
title: 'Hose Car',
category: 'chores'
}, {
title: 'Email Jethro',
category: 'work'
}, {
title: '400 lbs',
category: 'lifting'
}]
};
$scope.mappedTasks = $scope.tasklist.tasks.map(function(task) {
task.category = $scope.taskCategories.categories.indexOf(task.category);
return task;
}).sort(function(a, b) {
return a.category > b.category;
});;
console.log($scope.mappedTasks);
}
]);
.cat1_li {
background-color: yellow;
}
.cat2_li {
background-color: cyan;
}
.cat3_li {
background-color: pink;
}
.cat4_li {
background-color: lime;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="MainController">
<ul class="tasks">
<li ng-repeat="task in mappedTasks" class="cat{{ task.category + 1 }}_li">
<span>
<span class="panel_title">
{{ task.title }}
</span>
</span>
</li>
</ul>
</div>
Each ng-repeat creates a child scope with the passed data, and also adds an additional $index variable in that scope.
So what you need to do is reach up to the parent scope, and use that $index.
HTML :
<li ng-repeat="tasks in tasklist.tasks | orderBy:'category' | filter: {category: cat}" class="cat{{ $parent.$index + 1 }}_li">

Categories

Resources