How do I get a data value into a link - vuejs2

<td>{{ page.url }}</td>
<td>
<b-button href="#wiki/{{page.url}}" variant="primary">View</b-button>
</td>
I am trying to populate the href on my button.
I also have a router trying to do this
<script>
const router = new VueRouter({
routes:[{
path : '/:id',
name : 'wiki',
component : Detail
}
]
});
</script>

Use v-bind or the colon shortcut
<b-button :href="'#wiki/' + page.url">

Related

vuejs Dymanic Routes get param Id

user/index.vue
<tbody>
<tr
v-for="item in items"
:key="item.id"
>
<td v-if="false" v-text="item.id" />
<td v-text="item.name" />
<td v-text="item.phone" />
<td> <a #click="go(item.id)"> Details </a> </td>
</tr>
</tbody>
.
.
.
methods: {
go(idUser){
this.$router.push({
path: '/opr/:id',
name: 'oprid',
params:{
id: idUser
}
})
}
}
files:
-user
-opr
_id.vue
index.vue
so, when I clicked in "details" the error 404 is showing.
you can see that is about a list(item), I created one function and I'm sending id, I do this to make it more dynamic.
First of all, update router.
{
path: '/users/opr/:id',
name: 'UserOpr',
component: UserOpr
},
You can use id in UserOpr as follow.
this.$route.params.id

Vue Reactivity issue, setting array element property

I'm having a reactivity issue in following example. I can't find what I'm doing wrong. Am I setting the vue data correctly or do I need to do something else?
I have an object model as follows;
export default {
data () {
return {
filteredSkillTiers: [{
name: '',
categories: [{
name: '',
recipes: [{ name: '', profit: '' }]
}]
}],
recipeFilterText: ''
}
}
In created() method, I fill this filteredSkillTiers with real data. When I check as console.log(this.FilteredSkillTiers), it seems fine.
And, in my template, I have a button with #click="CalculateRecipe(i, j, k) which seems to be working perfect.
Here is my template;
<div
v-for="(skilltier,i) in filteredSkillTiers"
:key="i"
>
<div
v-if="isThereAtLeastOneFilteredRecipeInSkillTier(skilltier)"
>
<h3> {{ skilltier.name }} </h3>
<div
v-for="(category,j) in skilltier.categories"
:key="j"
>
<div
v-if="isThereAtLeastOneFilteredRecipeInCategory(category)"
>
<v-simple-table
dense
class="mt-3"
>
<template v-slot:default>
<thead>
<tr>
<th class="text-left">{{ category.name }}</th>
<th class="text-left">Click to Calculate</th>
<th class="text-left">Estimated Profit</th>
</tr>
</thead>
<tbody>
<tr v-for="(recipe,k) in category.recipes" :key="k">
<template
v-if="recipe.name.toLowerCase().includes(recipeFilterText.toLowerCase())"
>
<td>{{ recipe.name }}</td>
<td>
<v-btn
dense
small
#click="CalculateRecipe(i, j, k)"
>
Calculate
</v-btn>
</td>
<td>{{ filteredSkillTiers[i].categories[j].recipes[k].profit }}</td>
</template>
</tr>
</tbody>
</template>
</v-simple-table>
</div>
</div>
</div>
</div>
And here is my method;
CalculateRecipe (skilltierIndex, categoryIndex, recipeIndex) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('profitResult')
}, 50)
}).then((profit) => {
this.filteredSkillTiers[skilltierIndex].categories[categoryIndex].recipes[recipeIndex].profit = 'new Profit'
console.log(this.filteredSkillTiers[skilltierIndex].categories[categoryIndex].recipes[recipeIndex].profit)
})
},
When I log to console, I can see that I'm modifying the object correctly. But my updated value is not reflected in the rendered page.
There is this thing I suspect, if I update an irrevelant component in this page (an overlaying loading image component), I can see that rendered table gets updated. I want to avoid that because updating a component returns me to top of the page.
<td>{{ filteredSkillTiers[i].categories[j].recipes[k].profit }}</td>
This profit property seems not reactive. I'm really confused and sorry that I couldn't clear the code more, Thanks.
Here's the article describing how exactly reactivity works in Vue 2.x. And yes, (in that version) you should never update a property of tracked object directly (unless you actually want the changes not to be tracked immediately).
One way (mentioned in that article) is using Vue.set() helper function. For example:
Vue.set(this.filteredSkillTiers[skilltierIndex]
.categories[categoryIndex].recipes[recipeIndex], 'profit', 'new Profit');
You might consider making this code far less verbose by passing recipe object inside CalculateRecipe function as a parameter (instead of those indexes), then just using this line:
Vue.set(recipe, 'profit', promiseResolutionValue);

VueJS - One component but make requests to 2 different addresses

I have a component MainTable that renders a table in which I display Tasks:
({title: String, body: String, etc.}).
This component also triggers created method hook to make a request to my API to http://localhost:3000/api/v1/tasks.
I want to have a button with a link (route) to all complete_tasks where I want to also render the same table (hence I made it a component) with all complete tasks.
This time however, I want this component to make a request to a different address to http://localhost:3000/api/v1/tasks/complete_tasks (to fetch all complete tasks).
Is it possible to achieve this?
//App.vue
<template>
<div class="container">
<div class="row">
<h2>Todos</h2>
<mainTable></mainTable>
</div>
</div>
</template>
<script>
import MainTable from './components/MainTable.vue'
export default {
components: {
'mainTable': MainTable
},
methods: {
}
}
</script>
//MainTable.vue
<template>
<table class="table table-sm table-striped">
<thead>
<tr>
<th>Title</th>
<th>Content</th>
<th colspan="3"></th>
<th><select-all-button></select-all-button></th>
<th><finishButton></finishButton></th>
<br>
<th><removeAllButton></removeAllButton></th>
</tr>
</thead>
<tbody>
<tr v-for="task in tasks">
<td>{{ task.title }}</td>
<td>{{ task.content }}</td>
<td>Show</td>
<td>Edit</td>
<td>Delete</td>
</tr>
</tbody>
</table>
</template>
<script>
import SelectAllButton from './buttons/SelectAll.vue';
import FinishButton from './buttons/FinishButton.vue';
import RemoveAllButton from './buttons/RemoveAllButton.vue';
export default {
components: {
'select-all-button': SelectAllButton,
'finishButton': FinishButton,
'removeAllButton': RemoveAllButton
},
data(){
return {
tasks: []
}
},
created(){
this.$http.get('tasks').then(function(data){
this.tasks = data.body.slice(0,20);
})
}
}
</script>
yes, of course, you can do it
you can make a method trigger on click
when you press the button make a request to your endpoint and get the data
and update your object tasks with new data
Is that clear?

Vue.js - data access with dynamic components

I have simple web page that shows a result list and users can switch between table or li style.
I got simple Vue with two dynamic components : results-array and results-list.
It works like a charm except when I switch from the first component to the second one: I loose results properties called in mustache (I got blank values with no error) :
{{contact.img_path}} does not show anything
whereas
<img :src="contact.img_path" /> works great
** UPDATE **
Here a simplified jsfiddle to try out: https://jsfiddle.net/eywraw8t/151906/
My files :
contact.js
var list = Vue.component('results-list', {
template: '#results-list-template',
props: ['display_mode', 'contacts']
});
var table = Vue.component('results-array', {
template: '#results-array-template',
props: ['display_mode', 'contacts'],
});
const app = new Vue({
el: '#app',
router,
data: {
currentResultsView: 'results-array',
display_mode: 'array',
contacts: [],
contact: { company: {}, phones: {}, section: {}, schedule_type: {}}, // Declaring Reactive Properties
phone: {} // Declaring Reactive Properties
},
created () {
this.navigate(this.$route.query.page);
},
methods: {
changeDisplay: function(event, type){
this.currentResultsView = (type == "array") ? "results-array" : "results-list";
this.display_mode = type;
console.log('contacts', this.contacts[0].lastname) // WORKS !
},
navigate: function(page){
var page = page > 0 ? page : 1;
axios.get('/', {params: {page: page, fulltext_search: this.fulltext_search, sort_dir: this.sort_dir}})
.then((response) => {
this.contacts = response.data.entries;
});
}
}
});
index.html
<ul>
<li #click="changeDisplay($event, 'hcard')" :class="{active:display_mode == 'hcard'}">Carte de visite</li>
<li #click="changeDisplay($event, 'vcard')" :class="{active:display_mode == 'vcard'}">Vignette verticale</li>
<li #click="changeDisplay($event, 'array')" :class="{active:display_mode == 'array'}">Tableau</li>
</ul>
<div id="app">
<script type="text-x-template" id="results-array-template">
<table>
<tr>
<th></th>
<th>Firstname</th>
<th>Lastname</th>
</tr>
<tr v-for="contact in contacts">
<td><img :src="contact.img_path" class="contact_img" /></td>
<td>{{ contact.firstname }}</td>
<td>{{ contact.lastname }}</td>
</tr>
</table>
</script>
<script type="text-x-template" id="results-list-template">
<ul>
<li v-for="contact in contacts">
{{contact.firstname}} <!-- **Does not show anything** -->
<img :src="contact.img_path" /> <!-- **Works great!** -->
</li>
</ul>
</script>
<div id="results" :class="display_mode" class="clearfix">
<keep-alive>
<component v-bind:is="currentResultsView" :display_options="display_options" :display_mode="display_mode" :contacts="contacts" ></component>
</keep-alive>
</div>
</div>
You should either remove the key contact from the data part of your Vue root instance, or use another name in the v-for iterator (e.g. v-for="myContact in contacts")
UPDATE
Also, you should not use script tags for the template - use template instead, because Chrome ignores non-JavaScript script tags.
The solution - https://codepen.io/TMCDOS/pen/gjYWNY
The solution is to move the two template scripts outside of the #app div

How can I access vue repeated item key from a method

I have an html page, which has a table and an iterated row using v-for:
<table id="app-4">
<tr v-for="(item, index) in results" :key="item.id">
<td>#{{ item.title }}</td>
<td>
<button v-on:click="deleteItem(index)">Delete</button>
</td>
</tr>
</table>
and I have this js code.
var app4 = new Vue({
el: '#app-4',
data: {
results: []
},
methods: {
deleteItem: function (index) {
this.results.splice(index,1);
//Can I access item key and tr properties from here and the delete button
}
},
mounted() {
axios.get('api.list.url').then(response => {
this.results = response.data;
})
}
});
In the deleteItem function, Can I access item key and tr properties and append text to the item delete button.
The traditional Vue approach would probably be to use references
<table id="app-4">
<tr v-for="(item, index) in results" :key="item.id" ref="rows">
<td>#{{ item.title }}</td>
<td>
<button v-on:click="deleteItem(index)" ref="deleteButtons>
Delete
</button>
</td>
</tr>
</table>
And in the code
deleteItem: function (index) {
this.results.splice(index,1);
//Can I access item key and tr properties from here?
// Yes, e.g. to get the text content of the first cell
const text = this.$refs.rows[index].cells[0].textContent.trim();
// And add it to the delete button text
this.$refs.deleteButtons[index].textContent += " " + text;
}
Of course, that example is a bit nonsensical since you know the item's title, but the principle works for other properties of the text row (e.g. attributes, computed styles, classes, etc.)