Vue add existing Firebase ID for "relation" - javascript

I am using Vue and Firebase via VueFire to build a form to relate objects. I have the following form and method:
<form #submit.prevent="addRelation">
<select v-model="newRelation.parent">
<option v-for="item in content">{{item.name}}</option>
</select>
<select v-model="newRelation.child">
<option v-for="item in content">{{item.name}}</option>
</select>
<input type="submit" value="Add Relation"/>
</form>
And Vue:
new Vue({
el: "#app",
data: {
related: {},
newRelation: {
parent: '',
child: ''
}
},
firebase: {
content: contentRef,
related: relatedRef
},
methods: {
addRelation() {
relatedRef.push(this.newRelation)
console.log('relation added')
}
},
This adds JSON like so in Firebase:
{
"child": "objectc",
"parent": "objecta",
".key": "-KjFYZn8dqP29uLmJBJP"
},
It pushes a new Firebase ID and nests the data. In order for Firebase to handle 'relationships' correctly they must be structured like so:
{
".key":"-Existing ID of object A
"-Existing ID of object B": true
}
How can I update my method to structure info like so? I have this CodePen The bottom two entries in the "'Related' Content" section show how I want it to submit (I added manually).

Related

How to Store Data Property Value from a Specific Item in Rendered List in Vue

I'm trying create a follow button on list items in Vue. My strategy is to grab the value of a particular list item property and store it in the data object. Then use this value in a method to add it to an array in my database.
<div v-for="result in results" :key="result.symbol">
{{ result.name }}
<button #click="followStock">+follow</button>
</div>
I'm not sure how to get the value of result.symbol "into" the button element to set the value symbol in the data object below.
<script>
export default {
data() {
return {
results: [ // this is populated by an api call
{
currency: "USD"
exchangeShortName: "NYSE"
name: "International Game Technology PLC"
stockExchange: "NYSE"
symbol: "IGT"
},
{...},
...
],
symbol: "",
};
},
followStock() {
// add this.symbol to database array
},
},
};
</script>
I'm guessing there might be an easier strategy I'm overlooking as I'm still new to Vue, so any other solution that essentially allows me to fire off the value of result.symbol from any rendered result to my database would be awesome.
You can just pass the result as a parameter to your method.
<div v-for="result in results" :key="result.symbol">
{{ result.name }}
<button #click="followStock(result)">+follow</button>
</div>
And in your method:
methods: {
followStock(result) {
// do something with result
console.log({result});
let symbol = result.symbol;
},
}
P.S I didn't see you put your followStock() inside a methods object, but I did so in the example. https://v2.vuejs.org/v2/api/#methods
Write directly as a function call.
The vue compiler will turn followStock(result.symbol) into function(event) {followStock(result.symbol)}.
new Vue({
el: '#app',
data() {
return {
results: [
{
name: "International Game Technology PLC",
symbol: "IGT"
},
{
name: "A name",
symbol: "A symbol"
}
]
};
},
methods: {
followStock(symbol) {
console.log(symbol)
},
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div v-for="result in results" :key="result.symbol">
{{ result.name }}
<button #click="followStock(result.symbol)">+follow</button>
</div>
</div>
As Nazaire mentioned you can access the results anywhere inside the child elements when using v-for.
(it works like a normal for-loop)
It's not only limited to the corresponding element (the element in which you do v-for)
<div v-for="result in results" :key="result.symbol">
{{ result.name }}
<button #click="followStock(result.symbol)">+follow</button>
</div>
followStock(symbol){
// you can now add symbol to db
}

Vue, get value and name of select option

I'm using html and laravel to build select box options in a foreach loop
This works and populates with ID as value and name as the option. What I want, and can't quite figure out here, is how to take my function when I call it and get the id and value as separate vue options for a post axios call I'm going to make.
So when I select the option and submit the form to call the function, how can I get the ID as one prop and the name as another?
<select>
#foreach($details as $detail)
<option value="{{$detail->id}}">{{$detail->name}}</option>
#endforeach
</select>
new Vue({
data: {
detailID: [''],
detailName: ['']
},
methods: {
let data = {
detailID: this.detailID,
detailName: this.detailName
};
}
})
Here is a code example just using vue.js
Template
<div id="app">
<select v-model="selectedDetailId">
<option v-for="detail in details" v-bind:value="detail.id">
{{ detail.name }}
</option>
</select>
</div>
Script
new Vue({
el: '#app',
data: {
selectedDetailId: null,
details: [
{ id: 1, name: 'A' },
{ id: 2, name: 'B' },
{ id: 3, name: 'C' }
]
},
methods:{
post(){
//your selected Id is this.selectedDetailId
}
}
})
You can find more details and examples in the official Vue.js docs.
https://v2.vuejs.org/v2/guide/forms.html#Value-Bindings
Use v-model to bind the selection to your component data. SeeForm input bindings:
new Vue({
data: {
detailID: ""
},
// now you can access the id with this.detailID in your post request
})
<select v-model="detailID">
#foreach($details as $detail)
<option value="{{$detail->id}}">{{$detail->name}}</option>
#endforeach
</select>
And if you need both id and name, one work around could be:
new Vue({
data: {
detail: ""
},
// now you can access the id & name with this.detail.split(',') in your post request
})
<select v-model="detail">
#foreach($details as $detail)
<option value="{{$detail->id.','.$detail->name}}">{{$detail->name}}</option>
#endforeach
</select>
You would need to set a v-model to your select element and bind the entire object to each option element instead of just the id like you are doing in your example.
Here is a codepen with a simple example.

How can I update the button clicked in bootstrap-vue

I am using Bootstrap-Vue to display a table, and I've added in an extra column with an update button using vue-slot. I have this displaying fine, and I have a method being called when you click the button. Within that method I can access all the information on the item however I can't seem to find a way to access the button. I want to disable it and change the contents of it. How can I access the button element? I have created a codepen example here that shows what I have set up and need to do.
HTML
<div id='app'>
<div>{{ this.output }}</div>
<b-table hover head-variant="dark"
id="pages-table"
:items="items"
:fields="fields">
<template slot="actions" slot-scope="data">
<button class="btn btn-dark" #click="update(data)">Update</button>
</template>
</b-table>
</div>
JavaScript
new Vue({
el: "#app",
data: {
output: null,
items: [
{
id: 1,
name: "Tony"
},
{
id: 2,
name: "John"
},
{
id: 3,
name: "Paul"
}
],
fields: [
{
key: "id",
label: "ID",
sortable: true
},
{ key: "name" },
{ key: "actions" }
]
},
methods: {
update(data) {
// I need to disable the button here
this.output = data;
data.item.name = "Dave";
}
}
});
You could add a dynamic ref to the button
<button class="btn btn-dark" #click="update(data)" :ref="'btn' + data.index">Update</button>
And then just access the button by that ref
this.$refs["btn" + data.index].disabled = true
This is a codepen with the example
https://codepen.io/vlaem/pen/gNjGQE
Instead of the index you could also use the id property of your data to create the ref (data.item.id)
Though personally this doens't feel right, I think it would be better if we could track the status of all the buttons on the same or a different array, maybe like in the following example
https://codepen.io/vlaem/pen/GbBMLe

How to get select option in Vue.js

I am try to use Vue.js. I write javascript code like...
new Vue({
el: '#app',
data: {
classes: []
},
created: function () {
var vm = this
// Fetch API
fetch(xxx.json)
.then(function (response) {
return response.json();
})
.then(function (data) {
vm.classes = data.classes;
})
}
});
The program will fetch a JSON file first.The JSON format like
{
"classes": [
{
"name": "A",
"students": [
{
"name": "Eric",
"fruit": [
"apple",
"banana",
"orange"
]
},
{
"name": "Eickson",
"fruit": [
"banana",
"orange"
]
}
]
},
{
"name": "B",
"students": [
{
"name": "Ethan",
"fruit": [
"banana",
"apple"
]
}
]
}
]
}
Then put the JSON data into the data . Then I want the user can pick the items in each class. And use HTML to draw each class and each student
Imgur
HTML Code like...
<div class="row">
<div class="col-3" v-for="class in classes">
Class name: {{ class.name}}</br>
<div class="form-group row" v-for="student in cless.students">
<label class="col-form-label col-sm-2">{{ student.name }}</label>
<div class="col-sm-10">
<select class="form-control" :name="class.name+'-'+student.name">
<option></option>
<option v-for="fruit in class.fruit">{{fruit}}</option>
</select>
</div>
</div>
</div>
</div>
<button type="submit" " class="btn btn-primary">Submit</button>
I want to use the submit button to get all the selected option.
I tried to put a function in method. And button add #click="submitFunc() . But I have no idea to do it...
Please help me how to implement it. Thanks.
There are a couple immediate ways.
First, you can take the selected item from the select element by simple adding a method and taking the option natively.
Create a method submitFunc in your component's method options, in that method, query the select element.
new Vue({
//...
methods: {
submitFunc: function(){
let select = this.$el.querySelector('#mySelect'); //add an id for ease
let selectedOption = select.options[select.selectedIndex];
console.log(selectedOption); //will output the element, you can get the value at this point.
//do something else
}
}
})
Secondly, thanks to #Kokodoko, you can use the Vue's two-way data binding by declaring a selectedItem property in the data options, attaching it in the v-model attribute of the select element, and then accessing it via submitFunc method.
new Vue({
el: '#app',
data: {
classes: [],
selectedItem: null //this will be your selected option
},
methods:{
submitFunc: function(){
const selectedItem = this.selectedItem;
//do something with selectedItem
}
}
});
In the template
<select v-model="selectedItem">
<option></option>
<option v-for="fruit in class.fruit">{{fruit}}</option>
</select>
<button v-on:click="submitFunc">Submit</button>

Trying to bind the query to the json string for every request in to the api in Vue.js

I'm trying to get results from an api based on the user search box. When the user enters a value 'en' or 'de'. They should get the result from that search. I need to bind the user input into my query string. This works when I manually code the country into the template, but not when I bind the value into the string after the user inputs a value for the second time. The 'get' request that uses the user input value 'query' works fine. But not when I bind this a second time
I want to be fit to access
results[i].query.name
But '.query' is not working when I query the data unless I enter the value manually '.en'
I have a json file that looks like the following
[
{
"en": {
"name": "testone",
"id": 5363289,
"location": "messages_en.properties1"
},
"de": {
"name": "testonede",
"id": 5363289,
"location": "messages_en.properties2"
}
},
{
"en": {
"name": "test2",
"id": 5363289,
"location": "messages_en.properties3"
},
"de": {
"name": "test2de",
"id": 5363289,
"location": "messages_en.properties4"
}
}
]
Below is my index.html vue.js template
<div id=#app>
<input type="text" v-model="query" placeholder="Choose Language" />
<div class="medium-6 columns">
<a #click="getResult(query)" class="button expanded">Retrieve</a>
</div>
<template v-for="(result, i) in results">
<div class="card" style="width: 20rem; display:inline-block;">
<div class="card-block"></div>
<p> {{results[i].query}} </p>
<!-- works when I manually code in the 'en' query but when ran with 'query' it returns an error 'Cannot read property 'name' of undefined"' second time it returns that the value is -->
<!-- <p> {{results[i].en.name}} </p> -->
<!-- <p> {{results[i].query.name}} </p> -->
</div>
</template>
</div>
Vue.js
el: '#app',
data () {
return {
search: '',
query: 'en',
results: '',
title: '',
items: '',
section: ''
}
},
methods: {
getResult(query) {
axios.get('http://localhost:3000/api/country?country=' + query + '&blank=true').then(response => {
this.results = response.data;
console.log(this.results);
});
},
You need to use bracket notation to access a property using a param, so:
results[i][query].name
The second issue is that results[i][query] will be undefined until the async call has completed, so you will need to check that the property is not undefined or use a boolean flag. So, to check that it is not undefined you could do something like:
<p v-if="!!results[i][query]">{{results[i][query].name}}</p>
<p v-else>Loading...</p>
Here's a simplified JSFiddle for that: https://jsfiddle.net/4w3dxm22/
Or you could just use a dataLoaded flag:
new Vue({
el: '#app',
methods:{
getResult(query) {
this.dataLoaded = false; // set dataLoaded to false
axios.get('http://localhost:3000/api/country?country=' + query + '&blank=true').then(response => {
this.results = response.data;
this.dataLoaded = true; // Data has loaded so set dataLoaded to true
});
},
data: {
dataLoaded: false
}
})
Then you can do:
<span v-if="dataLoaded">{{results[i][query].name}}</span>
<span v-else>Loading Data...</span>
Here's the simplified JSFiddle for that: https://jsfiddle.net/99ydx82u/

Categories

Resources