I have my firebase DB with this tree structure.
I use vue-fire to loop through the database. I want to retrieve the "CantFindMe" value in the name property. My files look like this:
// Dashboard.vue
<template>
<div class="">
<ul>
<li v-for="personName in names" v-bind:key="personName['.key']">
<div v-if="!personName.edit">
<p>{{ personName.forms.step1 }}</p>
</div>
</li>
</ul>
</div>
</template>
<script>
import { namesRef} from '../firebase.js'
export default {
name: 'app',
data () {
return {
name: ''
}
},
firebase: {
names: namesRef
}
}
</script>
// Firebase.js
{ The usual firebase config }
{...}
export const firebaseApp = firebase.initializeApp(config)
export const db = firebaseApp.database()
export const namesRef = db.ref('names')
I manage to read the object: { "-KxrySGBHgLvw_lPPdRA": { "edit": false, "name": "CantFindMe" } }
But when I try to add ".name" after ".step1", that should supposedly return "CantFindMe", I get nothing/blank back.
How do I get to the name property using VueJs to return "CantFindMe"?
Sorry for delay, Im not using vuefire... So, first - do not refer to names only, but directly to step1:
export const namesRef = db.ref('names/EcoClim/forms/step1/')
You will obtain structure like this:
[{
".key": "-KxrySGBHgLvw_lPPdRA",
"edit": "false",
"name": "CantFindMe"
}, {
...
}]
Now you can use it in template, but as key, refer to array index and not to FBase key:
<li v-for="(person, idx) in names" :key="idx">
<div v-if="!person.edit">
<p>{{ person.name }}</p>
</div>
</li>
Related
I have a search bar on the root component (App.vue). I want to enter a query and on #keyup.enter, it should redirect to the Search component view with the v-text-field input value. Redirection is used by using $router.replace because users might search for a different keyword from within the same route.
The code below work but only ONCE. If I enter a new search term, the URL changed but the results stay the same.
App.vue
<template>
<div>
<header>
<v-text-field #keyup.enter="goToSearchPage($event)"></v-text-field>
</header>
<v-main>
<router-view></router-view>
</v-main>
</div>
</template>
<script>
export default {
methods: {
goToSearchPage($event) {
this.$router.replace({
name: "Search",
query: { q: $event.target.value }
});
}
}
};
</script>
views/Search.vue
<template>
<div>
<ais-instant-search
index-name="dev_brunjar_products"
:search-client="searchClient"
:search-function="searchFunction"
>
<ais-hits>
<ul slot-scope="{ items }">
<li v-for="item in items" :key="item.objectID">
{{ item.name }}
</li>
</ul>
</ais-hits>
</ais-instant-search>
</div>
</template>
<script>
import algoliasearch from "algoliasearch/lite";
export default {
data() {
return {
searchClient: algoliasearch(
process.env.VUE_APP_ALGOLIA_APP_ID,
process.env.VUE_APP_ALGOLIA_SEARCH_KEY
)
};
},
methods: {
// According to Algolia's doc, this should be inside data instead of methods
// https://www.algolia.com/doc/api-reference/widgets/instantsearch/vue/#widget-param-search-function
// But doing so, I wouldn't be able to get this.$route.query.q
searchFunction(helper) {
var query = this.$route.query.q;
if (query) {
helper.setQuery(query).search();
}
}
}
};
</script>
What I've tried
Did a hack-ish way (Test 1) to solve it but didn't work (which I'm glad, because it doesn't feel right). Below was the non-working code addition to the Search component. Created computed & watch property of query which get its data from this.$route.query.q and algoliaHelper data assigned with AlgoliaSearchHelper when the searchFunction first load.
When I typed a new search term, the watcher works and the query indeed changed. Despite that, calling the helper and setting its query with the new term within the watcher did not change the results from Algolia.
Then I used Routing URLs (Test 2) to the ais-instant-search and it still didn't solve the issue. Maybe I'm implementing it wrong? I really tried to understand Algolia's doc and it's just too hard to digest.
views/Search.vue - Test 1 (Failed)
<template>
<div>
<ais-instant-search
index-name="dev_brunjar_products"
:search-client="searchClient"
:search-function="searchFunction"
>
<ais-hits>
<ul slot-scope="{ items }">
<li v-for="item in items" :key="item.objectID">
{{ item.name }}
</li>
</ul>
</ais-hits>
</ais-instant-search>
</div>
</template>
<script>
import algoliasearch from "algoliasearch/lite";
export default {
data() {
return {
searchClient: algoliasearch(
process.env.VUE_APP_ALGOLIA_APP_ID,
process.env.VUE_APP_ALGOLIA_SEARCH_KEY
),
algoliaHelper: null
};
},
computed: {
query() {
return this.$route.query.q;
}
},
watch: {
query(newQuery) {
this.algoliaHelper.setQuery(newQuery).search();
}
},
methods: {
searchFunction(helper) {
if (!this.algoliaHelper) {
this.algoliaHelper = helper;
}
if (this.query) {
helper.setQuery(this.query).search();
}
}
}
};
</script>
views/Search.vue - Test 2 (Failed)
<template>
<div>
<ais-instant-search
index-name="dev_brunjar_products"
:search-client="searchClient"
:search-function="searchFunction"
:routing="routing"
>
<ais-hits>
<ul slot-scope="{ items }">
<li v-for="item in items" :key="item.objectID">
{{ item.name }}
</li>
</ul>
</ais-hits>
</ais-instant-search>
</div>
</template>
<script>
import { history as historyRouter } from "instantsearch.js/es/lib/routers";
import { singleIndex as singleIndexMapping } from "instantsearch.js/es/lib/stateMappings";
import algoliasearch from "algoliasearch/lite";
export default {
data() {
return {
searchClient: algoliasearch(
process.env.VUE_APP_ALGOLIA_APP_ID,
process.env.VUE_APP_ALGOLIA_SEARCH_KEY
),
routing: {
router: historyRouter(),
stateMapping: singleIndexMapping("instant_search")
}
};
},
methods: {
searchFunction(helper) {
if (this.query) {
helper.setQuery(this.query).search();
}
}
}
};
</script>
I would appreciate it if you guys know how to solve this issue.
https://codesandbox.io/s/github/algolia/doc-code-samples/tree/master/Vue%20InstantSearch/routing-vue-router?file=/src/views/Home.vue
This is an example using vue router. I guess this might be what you're looking for.
Please let us know if it works for you.
Hope you where able to solve this since it's been a long time since you asked. But, in order to make it work you have to put searchFunction(helper) inside data() as shown in the docs: https://www.algolia.com/doc/api-reference/widgets/instantsearch/vue/#widget-param-search-function
I have a static array data like this
const names = ["Amy", "Joseph", "Hank"];
I want to loop them in my markup, in React, I can simply do this:
import React, { memo } from "react";
// these guys are static values!
const names = ["Amy", "Joseph", "Hank"];
const App = () => (
<div>
{names.map(name => ( // render once and no more!
<span key={name}>{name}</span>
))}
</div>
);
export default memo(App); // won't re-render anymore!
But in Vue, the only way I can think of is doing this:
<template>
<div>
<span v-for="name in names" :key="name">{{ name }}</span>
</div>
</template>
<script>
const names = ["Amy", "Joseph", "Hank"];
export default {
data() {
return {
names // I have to put these guys in data property, now it becomes reactive, I don't want this. Although this will only render once.
};
}
};
</script>
I have to put my names in data() or computed properties, but this will cause them to be reactive, is there any other way to do this?
You can create a custom option like so
export default {
data() {
return {
//your reactive thins here
};
}
names : ["Amy", "Joseph", "Hank"],
.......
};
And finally in your template you can iterate over it like
<template>
<div>
<span v-for="name in $option.names">{{ name }}</span>
</div>
</template>
I am creating a Vue JS app which will display a list of products that when clicked on will link through to a dynamic product by its ID (passed via Vue Router params). This bit works fine but what I need to do is once on that dynamic route, display all the data for that product by its ID. I'm still pretty new to Vue and confused by what approach to take. I don't think I need axios as this won't be an online app so no access to APIs. I also don't know if I need to go as far as using vuex. At present I'm trying to use a simple method to grab the data from my JSON file by the ID passed through the routes parameters. Here's what I have so far...
router.js
import Vue from 'vue'
import Router from 'vue-router'
import Home from './views/Home.vue'
import Products from './views/Products.vue'
import Product from './views/ProductSingle.vue'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'home',
component: Home
},
{
path: '/products',
name: 'products',
component: Products
},
{
path: '/product/:id',
name: 'product',
component: Product,
props: true
}
]
})
Slider.vue - this component is called in Views/Products.vue and is what links through to each single product
<template>
<carousel
:items="3"
:loop="true"
:center="true"
:margin="0"
:dots="false"
:nav="true"
>
<div v-for="product in products" :key="product.productId">
<transition name="slide">
<router-link
:to="{
name: 'product',
params: { id: product.productId }
}"
>
<img src="http://lorempixel.com/100/100/city" :alt="product.name" />
<!-- <img
:src="require('../assets/images/sample-product/' + data.image)"
/>-->
</router-link>
</transition>
</div>
</carousel>
</template>
<script>
import json from '#/json/data.json'
import carousel from 'vue-owl-carousel'
export default {
data() {
return {
products: json
}
},
components: {
carousel
}
}
</script>
ProductSingle.vue
<template>
<div>
<p v-for="product in getData($route.params.id)" :key="product.productId">
{{ product }}
</p>
</div>
</template>
<script>
import json from '#/json/data.json'
export default {
data() {
return {
products: json
}
},
methods: {
getData(id) {
let data = this.products
data.filter(item => {
return item.productId == id
})
}
}
}
</script>
What I as expecting here is that my getData method would return the data for the product at the ID denoted through $route.params.id yet nothing is returned. A console.log(getData($route.params.id)) shows the following:
[{…}]
Which when expanded out shows 0: {__ob__: Observer} and if you expand that observer out there is indeed that data for
image: (...)
name: (...)
productId: (...)
My data.json file looks like the below:
[
{
"productId": 1,
"name": "Test 1",
"image": "sample.jpg"
},
{
"productId": 2,
"name": "Test 2",
"image": "sample.jpg"
},
{
"productId": 3,
"name": "Test 3",
"image": "sample.jpg"
},
{
"productId": 4,
"name": "Test 4",
"image": "sample.jpg"
}
]
Could really do with some guidance on how to approach this problem.
Many thanks in advance
You're missing a return here:
data.filter(item => {
return item.productId == id
})
Try this:
return data.filter(item => {
return item.productId == id
})
If you're not using Api or Vuex then you need to have all the data on a place where they can be fetched from multiple components.
data.json is fine for this.
On your child component, do the following. There is no need for data iteration.
<template>
<div>
{{ singleProduct }}
{{ singleProduct.productId }}
</div>
</template>
<script>
import json from '#/json/data.json'
export default {
name: 'ProductSingle',
data() {
return {
products: json,
singleProduct: undefined
}
},
computed: {
productId () {
return this.$route.params.id // From route
}
},
created () {
this.assignSingleProduct();
},
methods: {
assignSingleProduct() {
let data = this.products
data.filter(item => {
return item.productId == this.productId
})
// Assign to the data
this.singleProduct = data
}
}
}
</script>
I did [GET] method using Axios. Everything is working fine, when I want to output i get this kind of thing:
http://prntscr.com/mpey70
This is my JS with HTML and VUE code on how I am trying to output it:
HTML, VUE:
<div class="col-lg-6">
<p>Casuals</p>
<ul>
<div v-bind:key="realsub.id+1" v-for="realsub in subnavreal">
<div v-if="nav.linkTitle == 'Male'">
<li><router-link :to="{ path: whiteSpace(realsub.male.casual) }">{{JSON.realsub.male.casual}}</router-link></li>
</div>
<div v-if="nav.linkTitle == 'Female'"></div>
<li><router-link :to="{ path: whiteSpace(realsub.female.casual) }">{{realsub.female.casual}}</router-link></li>
</div>
</ul>
</div>
And this is Related JS code:
import axios from 'axios';
import uuid from 'uuid';
export default {
name: 'navigation',
data(){
return{
subnavreal: []
}
},
props: ["navigation"],
methods:{
whiteSpace(a){
console.log(a);
}
},
async created(){
axios.get('/products.json')
.then(res => this.subnavreal = res.data)
.catch(err => console.log(err));
}
}
</script>
What I want to display is only the name of that object, for example: "Hoodies"
Any solutions? :)
I think you are printing the entire Response. You can use the Object.keys() to print the keys.
let user = {
name: "tom",
age: 20
}
If you want to print the keys [name, age] use Object.keys(user)
I want some help in getting data form json array file is in the link
Html
<div>
<div v-for="data in myJson.id " >{{ data }}</div>
</div>
js
import json from '.././json/data.json'
export default {
components: {
MainLayout,
},
data: function(){
return {
myJson:json
}
},
method:{
getjson:function(){
this.json = JSON.parse(myJson);
}
}
}
i want to access only the data with some specific id and i cannot access it using the syntax i am using
edit
Json file
Apparently, you do not even need JSON.parse. It seems to work without it... Put your JSON file in the same directory as your component and try this:
import data from './data.json'
export default {
created () {
for (const item of data[0]['file']) {
console.log(`
Name: ${item.name}
Type: ${item.type}
Size: ${item.filesize}
Dimensions: ${item.dimension[0].width}x${item.dimension[0].height}
`)
}
}
}
You should see information from your JSON file in your console when the page loads.
<script>
import MainLayout from '../layouts/Main.vue'
import json from '.././json/data.json'
export default {
components: {
MainLayout,
},
data: function(){
return {
myJson: json[0].file
}
},
method:{
}
}
</script>
html
<div v-for="data in myJson">
{{ data.name }}
{{ data.filesize}}
{{ data.dimension[0].width}}x{{data.dimension[0].height}}
</div>
using the above code i utilized and used to implemented according to my needs and it worked