Im new in vue.js and im facing frontend issue hot to add Edit button in every row dynamically this my
<template>
<div>
<NavBar />
<div class="container mt-3">
<h3>FOO</h3>
<div>
<b-table striped hover :items="items"></b-table>
</div>
</div>
</div>
</template>
and this how I fetching the items
export default {
name: "PageTemplateView",
components: {
NavBar,
},
data() {
return {
items: []
}
},
mounted() {
axios
.get("http://localhost:1001/")
.then((res) => {
let objek = res.data.data;
objek = objek.topping
this.items = objek;
})
.catch(function (error) {
console.log(error);
});
},
};
I want to add new field action after field Type, and render the button for edit every row i choosed
Specify the fields and pass them to your table.
data: () => ({
fields: [
'id', 'type', 'actions'
]
})
In template:
<b-table :items="items" :fields="fields">
<template #cell(actions)="{item}">
Go wild...
</template>
</b-table>
You can see all available scope props of cell({key}) slot here.
Working example here
Related
<template v-for='item in 777'>
<ParentComponent>
<ChildComponent /
</ParentComponent>
</template>
Now, I want some events in ParentComponent to trigger some events in ChildComponent, however it's rendering generated components, I don't want to use Ref and prove&inject to do this, is there a more elegant way to implement it?
You can try with scoped slot, prop and watcher:
const app = Vue.createApp({})
app.component('parent', {
template: `
<div>
<button #click="trigger = true">evt</button>
<slot :trig="trigger"></slot>
</div>
`,
data: () => ({
trigger: false,
}),
})
app.component('child', {
template: `
<div>{{ evt }}</div>
`,
props: {
trig: {
type: Boolean,
default: false
}
},
data: () => ({
evt: 'a',
}),
watch: {
trig(val) {
if(val) this.trigEvt()
}
},
methods: {
trigEvt() {
this.evt = 'b'
}
}
})
app.mount('#demo')
<script src="https://unpkg.com/vue#3/dist/vue.global.prod.js"></script>
<div id="demo">
<template v-for='item in 7'>
<parent>
<template v-slot="{trig}">
<child :trig="trig"></child>
</template>
</parent>
</template>
</div>
ers,
Experiencing a strange rendering issue. I am grabbing user data from localForage located in my Vuex store in a promise in the following component:
<template>
<div>
<h1>Users available for test {{ $route.params.id }}</h1>
<v-form>
<div v-if="this.import_complete">
<UserList
:users="users"
/>
</div>
</v-form>
</div>
</template>
<script>
import UserList from './UserList.vue';
export default {
name: 'UserManagement',
components: {
UserList,
},
data: () => ({
users: [],
import_complete: false,
}),
mounted() {
Promise.resolve(this.$store.getters.getUsersByTestId(
this.$route.params.testId,
)).then((value) => {
this.users = value;
this.import_complete = true;
});
},
};
</script>
Since it's a promise, I am setting a boolean import_complete to true, and a div in the template is only passing through the data as a prop when this boolean is true
Next, I am consuming the data in another template, in a for loop.
<template>
<div>
<v-container>
<v-banner v-for="user in this.users" :key="user.index">
{{ user.index }} {{ user.name }} {{ user.profile }}
<template v-slot:actions>
<router-link
:to="`/usering/${user.test}/user/${user.index}`">
<v-btn text color="primary">Open usering analysis</v-btn>
</router-link>
<v-btn text color="warning" #click="deleteUser(user.index)">Delete</v-btn>
</template>
</v-banner>
</v-container>
</div>
</template>
<script>
export default {
name: 'UserList',
props: {
users: Object,
},
methods: {
deleteUser(index) {
this.$store.dispatch('delete_user', index);
},
},
mounted() {
console.log('mounted user list, here come the users');
console.log(this.users);
},
};
</script>
The thing is, the first time it doesn't show anything. Only when I make a tiny change in the last component (can be an Enter followed by a save command) and suddenly the users are displayed on the page.
Interestingly, in the first scenario, the user's array is already filled, I see it in the console (created in the mount method) as well in the Chrome developer Vue tab.
It's probably some kind of Vue thing I am missing? Does someone have a clue?
[edit]
I've changed the code to this, so directly invoking the localForage. It seems to work, but I would still like to understand why the other code won't work.
this.test = this.$store.getters.getTestByTestId(this.$route.params.testId);
this.test.store.iterate((value, key) => {
if (key === (`user${this.$route.params.userId}`)) {
this.user = value;
}
}).then(() => {
this.dataReady = true;
}).catch((err) => {
// This code runs if there were any errors
console.log(err);
});
I'm building an app using VueJS with bootstrapVue for frontend and Django for backend. I'm using b-table and I would like to use pagination by b-pagination.
In my itemsProvider function I get the current page of the b-pagination like this ctx.currentPage and send a request to the back-end. The problem is that when I clicked on the buttons of the b-pagination the itemsProvider function isn't recalled, and I don't know why.
Below is a portion of code:
<template>
<div class="container">
<b-pagination v-model="currentPage" :totalRows="totalRows" :per-page="perPage"></b-pagination>
<p>Current page {{currentPage}}</p>
<b-table
current-page="currentPage"
per-page="perPage"
:items="itemsProvider"
:fields="fields"
>
</b-table>
</div>
</template>
<script>
import { mapActions } from "vuex";
export default {
name: "Archive",
data() {
return {
perPage: 10,
totalRows: 200,
pageOptions: [5, 10, 22],
currentPage: 1,
bookInfo: {},
fields: [...]
};
},
computed: {
books() {
return this.$store.getters["books/books"].filter(item => {
return item.status == "AR";
});
}
},
methods: {
...mapActions({
getArchivedBooks: "books/getArchivedBooks"
}),
itemsProvider(ctx, callback) {
console.log(ctx.currentPage)
let page = ctx.currentPage;
return this.getArchivedBooks(page).then(() => {
const items = this.books;
return items || [];
});
},
}
};
</script>
I should bind the perPage and currentPage values to b-table's props current-page and per-page like this:
<b-table
:current-page="currentPage"
:per-page="perPage"
:items="itemsProvider"
:fields="fields"
>
</b-table>
I'm building a chrome extension using vue.js. In one of my vue components I get tab informations of the current tab and wanna display this information in my template. This is my code:
<template>
<div>
<p>{{ tab.url }}</p>
</div>
</template>
<script>
export default {
data() {
return {
tab: {},
};
},
created: function() {
chrome.tabs.query({ active: true, windowId: chrome.windows.WINDOW_ID_CURRENT }, function(tabs) {
this.tab = tabs[0];
});
},
};
</script>
The Problem is, that the template gets the data before it's filled through the function. What is the best solution for this problem, when the tab data doesn't change after it is set once.
Do I have to use the watched property, although the data is only changed once?
// EDITED:
I've implemented the solution, but it still doesn't work. Here is my code:
<template>
<div>
<div v-if="tabInfo">
<p>set time limit for:</p>
<p>{{ tabInfo.url }}</p>
</div>
<div v-else> loading... </div>
</div>
</template>
<script>
export default {
data() {
return {
tabInfo: null,
};
},
mounted() {
this.getData();
},
methods: {
getData() {
chrome.tabs.query({ active: true, windowId: chrome.windows.WINDOW_ID_CURRENT }, function(tabs) {
console.log(tabs[0]);
this.tabInfo = tabs[0];
});
},
},
};
</script>
The console.log statement in my getData function writes the correct object in the console. But the template only shows the else case (loading...).
// EDIT EDIT
Found the error: I used 'this' in the callback function to reference my data but the context of this inside the callback function is an other one.
So the solution is to use
let self = this;
before the callback function and reference the data with
self.tab
You could initialize tab to null (instead of {}) and use v-if="tabs" in your template, similar to this:
// template
<template>
<div v-if="tab">
{{ tab.label }}
<p>{{ tab.body }}</p>
</div>
</template>
// script
data() {
return {
tab: null,
}
}
new Vue({
el: '#app',
data() {
return {
tab: null,
}
},
mounted() {
this.getData();
},
methods: {
getData() {
fetch('https://reqres.in/api/users/2?delay=1')
.then(resp => resp.json())
.then(user => this.tab = user.data)
.catch(err => console.error(err));
}
}
})
<script src="https://unpkg.com/vue#2.5.17"></script>
<div id="app">
<div v-if="tab">
<img :src="tab.avatar" width="200">
<p>{{tab.first_name}} {{tab.last_name}}</p>
</div>
<div v-else>Loading...</div>
</div>
I have a list that displays items on a page, on the same page you can open a dialog where you are able to add items to the list. When I close the dialog I want the list to re-render to also show the latest added item.
Parent:
<template>
<div v-for="item in listItems" :key="item.id"></div>
<app-card-grid-work
:items="listItems">
</app-card-grid-work>
<v-dialog v-model="dialog" max-width="500px">
<app-fab slot="activator"></app-fab>
<app-add-work #closeDialog="getWork()"></app-add-work>
</v-dialog>
<template>
export default {
data() {
return {
listItems: [],
},
methods: {
getWork(){
axios
.get("/workads")
.then(res => {
const data = res.data;
const ads = [];
for (let id in data) {
const ad = data[id];
ads.push(ad);
}
this.listItems = ads;
})
.catch(error => console.log(error));
},
},
},
};
Child (app-add-work)
<template>
<v-btn
#click="onSubmit"
:disabled="!valid">
Skapa
</v-btn>
<template>
<script>
export default {
//...
methods:{
onSubmit(){
this.$emit('closeDialog')
}
},
//...
};
</script>