Display data when click on button with Meteor - javascript

I have one button, when I click I want to display data only if the value of the checkbox is true, If it false, it's display when DOM is created
But I can't please look my code.
Template.students.helpers({
all_students: () => {
return students.find();
}
});
Template.body.onCreated(() => {
Meteor.subscribe('students');
});
Template.students.events({
'submit .insert': (e) => {
e.preventDefault();
students.insert({
name: e.target[0].value,
age: e.target[1].value,
check: false
});
this._checkValue(e);
},
'click .is-delete': (e) => {
students.remove(e.currentTarget.id);
},
'click .check-checkbox': (e) => {
students.update(e.currentTarget.id, {
$set: {
check: !this.check
}
})
},
'click .all': () => {
// HERE
}
})
<template name="students">
<div class="content menu">
<ul>
<button class="ui button all">All list</button> <!-- THIS BUTTON -->
{{#each all_students}}
<li class="content-list" id="{{ _id }}">
<div class="name">{{ name }}</div>
<div class="age">{{ age }} ans</div>
<span id="{{ _id }}" class="delete is-delete"></span>
<div class="ui checkbox">
<input id="{{ _id }}" class="check-checkbox" type="checkbox" name="check">
</div>
</li>
{{/each}}
</ul>
</div>
</template>
Inside of my event handler click .all if I try to return students.find() it doesn't work.

The easiest way is to use a ReactiveVar to flag if the list should show like so:
Add the ReactiveVar to your template instance
Template.students.onCreated(() => {
this.showAllStudents = new ReactiveVar(false);
this.subscribe('students');
});
Then expose it with a helper:
Template.students.helpers({
showStudents() {
Template.instance().showAllStudents.get();
},
all_students() {
students.find();
};
});
In your template, test for the flag
<template name="students">
<div class="content menu">
<ul>
<button class="ui button all">All list</button> <!-- THIS BUTTON -->
{{#if showStudents}}
{{#each all_students}}
<li class="content-list" id="{{ _id }}">
<div class="name">{{ name }}</div>
<div class="age">{{ age }} ans</div>
<span id="{{ _id }}" class="delete is-delete"></span>
<div class="ui checkbox">
<input id="{{ _id }}" class="check-checkbox" type="checkbox" name="check">
</div>
</li>
{{/each}}
{{/if}}
</ul>
</div>
</template>
And add the event handler which just switches the state (ie. set opposite of current state):
Template.students.events({
'click .all': (event, instance) => {
instance.showAllStudents.set(!instance.showAllStudents.get());
}
})
If you haven't already got it, run meteor add reactive-var to get the package.
And if you're using imports, use import { ReactiveVar } from 'meteor/reactive-var'; to import it.

Related

How to assign v-on dinamically with v-for

I have a code in Vue that creates the elements of a menu using a v-for, and each element must have a different method when it's clicked.
So far I have this:
<span v-for="(menuItem, index) in menuItems" :key="index">
<li>
<a id="listItem">
<i class="bx" :class="menuItem.icon || 'bx-square-rounded'" />
<span class="links_name" v-on:click=menuItem.click>{{ menuItem.name }}</span>
</a>
<span class="tooltip">{{
menuItem.tooltip || menuItem.name
}}</span>
</li>
</span>
How can I assign different funcions on the v-on?
You can make the listener function as a node in the object list.
Sample Implementation
const app = new Vue({
el: '#app',
data() {
return {
list: [{
name: 'lg',
age: 27,
onClick: function() {
console.log("First Item Clicked");
}
}, {
name: 'camile',
age: 27,
onClick: function() {
console.log("Second Item Clicked");
}
}]
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.0/vue.js"></script>
<body>
<div id="app">
<ul>
<li v-for="(item, index) in list" :key="item.name">
{{item.name}} - {{item.age}}
<button #click="item.onClick()">
Click Me
</button>
</li>
</ul>
<input type="text" v-model="list[0].name">
</div>
</body>

Vuejs emit not working form child to parent

I'm working on this app and the idea is to show details of the cars in a sidebar on click. There are several issues like the sidebar is showing four times and I resolve it somehow but I don't know why is it showing four times. now I don't getting any response on emit call help me out please, I try $parent.$emit, $root.$emit but not seems working!!!
<template>
<div class="home">
<!-- warehouse details -->
<div
v-for="(detail, detailindex) in details"
:key="detailindex"
class="container mt-5 mb-5"
>
<h1>
{{ detail.name }}
<span class="location">{{ detail.cars.location }}</span>
</h1>
<!-- vehicle details -->
<SingleGarage :detail="detail"> </SingleGarage>
</div>
<b-sidebar
id="my-sidebar"
title="Sidebar with backdrop"
backdrop-variant="dark"
ref="mySidebar"
backdrop
shadow
#emitData="testingEmit()"
>
<div class="px-3 py-2">
<h1>{{currentCar}}</h1>
</div>
</b-sidebar>
</div>
</template>
<script>
// # is an alias to /src
import axios from "axios";
import SingleGarage from "../components/SingleGarage";
export default {
components: { SingleGarage },
name: "Home",
data: () => ({
details: String,
currentCar: 'String',
}),
methods:{
testingEmit(data){
this.currentCar = data
console.log('data from emit',data)
}
},
mounted() {
axios
.get("https://api.jsonbin.io/b/5ebe673947a2266b1478d892")
.then((response) => {
var results;
response.data.forEach((element) => {
element.cars.vehicles.sort((a, b) => {
a = new Date(a.date_added);
b = new Date(b.date_added);
results = a > b ? -1 : a < b ? 1 : 0;
return results * -1;
});
});
this.details = response.data;
});
},
};
</script>
<template>
<div class="vGrid mt-4">
<div
class="gridItem border vehicle singleCar"
v-for="(vehicle, vehicleIndex) in detail.cars.vehicles"
:class="'griditem' + vehicleIndex"
:key="vehicle._id"
>
<SingleCar
:vehicle="vehicle"
#click.native="testingTef(vehicleIndex)"
></SingleCar>
</div>
</div>
</template>
<script>
import SingleCar from "#/components/SingleCar";
export default {
name: "SingleGarage",
components: { SingleCar },
props: ["detail"],
data: () => ({
dummyImg: require("#/assets/img/dummycar.png"),
currentCar : 1
}),
methods: {
testingTef(vehicleIndex) {
this.$parent.$emit('emitData',this.detail.cars.vehicles[vehicleIndex].make)
this.$root.$emit('bv::toggle::collapse', 'my-sidebar')
console.log(this.detail.cars.vehicles[vehicleIndex].make)
console.log(this.detail.cars.vehicles[vehicleIndex].date_added)
this.currentCar = this.detail.cars.vehicles[vehicleIndex].make;
},
},
};
</script>
<template>
<div class="singleCar">
<!-- conditionally show image -->
<img
class="carImg"
:src="vehicle.img"
v-if="vehicle.img"
alt="No Preview"
/>
<img class="carImg" :src="dummyImg" v-else alt="No Preview" />
<div class="p-3">
<h3 class="make">{{ vehicle.make }}</h3>
<div class="modelDetails">
<div class="model d-flex ">
<p class="bold">Model:</p>
<p class="price ml-auto ">{{ vehicle.model }}</p>
</div>
<div class="price d-flex ">
<p class="bold">Price:</p>
<p class="price ml-auto ">€{{ vehicle.price }}</p>
</div>
</div>
<p class="dateAdded ml-auto ">{{ vehicle.date_added }}</p>
</div>
</div>
</template>
<script>
export default {
name: "SingleCar",
props: ["vehicle"],
data: () => ({
dummyImg: require("#/assets/img/dummycar.png"),
}),
methods:{
working(){
console.log('working');
console.log(this.vehicle.make)
}
}
};
</script>
Thanks for your help.
So a few things you can try to fix this
in your Home.vue you can change
#emitData="testingEmit()"
to
#emitData="testingEmit"
// or
#emitData="testingEmit($event)"
You are telling to the function testingEmit that is not params to parse. So you need to take out the () and Vue will parse everything that comes from the $event or you cant say put the $event as a param in your testingEmit (second option).
For your SingleGarage.vue you can take the $parent.$emit and replace it with
this.$emit('emitData',this.detail.cars.vehicles[vehicleIndex].make)

emitting data from chiled to parent using vue.js and laravel

i new in vue.js i have test component is child and showdata component is parent my proplem is when i emit data from child to parent it is emitted successfully but when i show data in parent by #click="showusersdata1(listdata.id) i get empty data like attached image so how to show user data
here is my code
showdata.vue
<template>
<div>
id={{setUserData.id}},
name={{setUserData.name}}
email={{setUserData.email}}
<test v-on:showusersdata1="userData($event)"></test>
</div>
</template>
<script>
import MyHome from "./home";
// let Test=require('./components/test.vue').default
import test from "./test"
export default {
// components: {MyHome},
name: "showData",
data:function () {
return{
setUserData:{}
}
},
components:{
test
},
methods:{
userData:function (passedata) {
console.log(passedata)
// this.setUserData={}
this.setUserData= this.setUserData.push(passedata)
}
}
}
</script>
test.vue
<template>
<div class="row">
<div class="col-8">
<h1>this is test components1</h1>
<!-- List group -->
<div class="input-group mb-3">
<input type="text" class="form-control" placeholder="Recipient's username" aria-label="Recipient's username" aria-describedby="button-addon2">
<div class="input-group-append">
<button class="btn btn-outline-secondary" type="button" id="button-addon2">Button</button>
</div>
</div>
<div class="list-group" id="myList" role="tablist">
<a v-for ="(listdata,key) in list" class="list-group-item list-group-item-action active" data-toggle="list" href="#home" role="tab">
<ul class="test">
<i class="fas fa-trash" aria-hidden="true"></i>
<i class="fas fa-edit"></i>
<i #click="showusersdata1(listdata.id)" class="fas fa-eye"></i>
</ul> {{listdata.name}}</a>
</div>
</div>
<h1>this is cchiled show data coponent</h1>
</div>
</template>
<script>
import ShowData from "./showdata";
export default {
name: "Test",
components:{
ShowData
},
data: function () {
return {
list:{},
errors:{},
}
},
mounted(){
axios.post('/getAllData')
// .then((response) =>this.list=response.data )
.then((response) =>{
this.list=response.data
} )
.catch((error) =>this.errors=error.response.data.errors )
},
methods:{
showusersdata1:function (key) {
var index = this.list.find( ({ id }) => id == key );
this.$emit('userData', index)
}
}
}
</script>
<style scoped>
.test{
float:right
}
</style>
You are emiting here:
this.$emit('userData', index)
Which means the name of your event is 'userData'. That's what you have to listen to in the parent. But if you check your parent, you are listening to the event like this:
v-on:showusersdata1="userData($event)"
This means you are trying to listen to the 'showusersdata1' event, which is not fired. You are confusing the method name in your child for your event name. Instead of what you did, you can listen to your event like this:
v-on:userData="userData"
It's also kind of a convention to name event listeners by adding "on" in front of them, example:
event name is 'userDataReceived'
event listener would be onUserDataReceived

Refresh Boostrap-Vue table after deleting a row

I'm using Bootstrap-Vue for my datatables and got the following table within my dashboard:
I can succesfully delete items by clicking on the trash icon. It sends an AJAX request using Axios. However, after deletion it still displays the item until I manually refresh the web page. How do I solve this? I don't want to make another AJAX request to load in the updated version, I think the best way to solve it is just remove the deleted item row from the datatable.
I tried giving my table a ref tag and call a refresh function using this.$refs.table.refresh(); but with no success.
My code:
<template>
<div>
<b-modal ref="myModalRef" hide-footer title="Delete product">
<div class="container">
<div class="row">
<p>Are you sure you want to delete this item?</p>
<div class="col-md-6 pl-0">
Confirm
</div>
<div class="col-md-6 pr-0">
Cancel
</div>
</div>
</div>
</b-modal>
<div id="main-wrapper" class="container">
<div class="row">
<div class="col-md-12">
<h4>Mijn producten</h4>
<p>Hier vind zich een overzicht van uw producten plaats.</p>
</div>
<div class="col-md-6 col-sm-6 col-12 mt-3 text-left">
<router-link class="btn btn-primary btn-sm" :to="{ name: 'create-product'}">Create new product</router-link>
</div>
<div class="col-md-6 col-sm-6 col-12 mt-3 text-right">
<b-form-input v-model="filter" class="table-search" placeholder="Type to Search" />
</div>
<div class="col-md-12">
<hr>
<b-table ref="table" show-empty striped hover responsive :items="posts" :fields="fields" :filter="filter" :current-page="currentPage" :per-page="perPage">
<template slot="title" slot-scope="data">
{{ data.item.title|truncate(30) }}
</template>
<template slot="description" slot-scope="data">
{{ data.item.description|truncate(50) }}
</template>
<template slot="public" slot-scope="data">
<i v-if="data.item.public === 0" title="Unpublished" class="fa fa-circle false" aria-hidden="true"></i>
<i v-else title="Published" class="fa fa-circle true" aria-hidden="true"></i>
</template>
<template slot="date" slot-scope="data">
{{ data.item.updated_at }}
</template>
<template slot="actions" slot-scope="data">
<a class="icon" href="#"><i class="fas fa-eye"></i></a>
<a v-on:click="editItem(data.item.id)" class="icon" href="#"><i class="fas fa-pencil-alt"></i></a>
<i class="fas fa-trash"></i>
</template>
</b-table>
<b-pagination :total-rows="totalRows" :per-page="perPage" v-model="currentPage" class="my-0 pagination-sm" />
</div>
</div><!-- Row -->
</div><!-- Main Wrapper -->
</div>
<script>
export default {
data() {
return {
posts: [],
filter: null,
currentPage: 1,
perPage: 10,
totalRows: null,
selectedID: null,
fields: [
{
key: 'title',
sortable: true
},
{
key: 'description',
},
{
key: 'public',
sortable: true,
},
{
key: 'date',
label: 'Last updated',
sortable: true,
},
{
key: 'actions',
}
],
}
},
mounted() {
this.getResults();
},
methods: {
// Our method to GET results from a Laravel endpoint
getResults() {
axios.get('/api/products')
.then(response => {
this.posts = response.data;
this.totalRows = response.data.length;
});
},
getID: function(id){
this.selectedID = id;
this.$refs.myModalRef.show();
},
deleteItem: function (id) {
axios.delete('/api/products/' + id)
.then(response => {
this.$refs.myModalRef.hide();
this.$refs.table.refresh();
});
},
editItem: function (id){
this.$router.push({ path: 'products/' + id });
}
},
}
</script>
The deleteItem method should be like this:
deleteItem(id) {
axios.delete('/api/products/' + id)
.then(response => {
const index = this.posts.findIndex(post => post.id === id) // find the post index
if (~index) // if the post exists in array
this.posts.splice(index, 1) //delete the post
});
},
So basically you don't need any refresh. If you remove the item for posts array Vue will automatically handle this for you and your table will be "refreshed"
try to remove that post with the given id after the successful delete :
axios.delete('/api/products/' + id)
.then(response => {
this.posts= this.posts.filter(post=>post.id!=id)
});
axios.delete('/api/products/' + id)
.then(response => {
this.getResults();
});

Meteor: how to retrieve "{{this}}-value" with a template event

Note: Whole code can be found here:
https://github.com/Julian-Th/crowducate-platform/tree/feature/courseEditRights
The issue: I can't retrieve the {{this}} value with an event. Console.log() is printing 0.
My HTML:
<!-- Modal to control who can collaborate on a course-->
<template name="modalAddCollaborators">
<div id="modalAddCollaborators" class="modal fade" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Manage Your Collaborators</h4>
</div>
<div class="modal-body">
<form class="form" role="form">
<ul class="list-group">
{{#each addedCollaborators}}
{{#each canEditCourse}}
<li class="list-group-item js-listed-collaborator">{{this}}<a title="Remove Collaborator" id="remove-collaborator" class="btn btn-danger pull-right" href="#"><i class="fa fa-trash"></i></a></li>
{{/each}}
{{/each}}
</ul>
<div class="form-group">
<input class="form-control typeahead" type="text" id="collaboratorName" placeholder="add a collaborator ..." data-source="courses" autocomplete="off" spellcheck="off">
<button type="button" id="js-addCollaborator" class="btn btn-success">Add</button>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
</template>
My JS:
Template.modalAddCollaborators.rendered = function() {
// initializes all typeahead instances
Meteor.typeahead.inject();
};
Template.modalAddCollaborators.courses = function(){
return Courses.find().fetch().map(function(it){ return it.author; });
//return users.find().fetch().map(function(it){ return it.username; });
};
Template.modalAddCollaborators.helpers({
'addedCollaborators': function () {
return Courses.find().fetch();
}
});
Template.modalAddCollaborators.events({
'click #js-addCollaborator' : function (event) {
var collaboratorName = $('#collaboratorName').val(); //
Courses.update(
{_id: this._id},
{$addToSet: {canEditCourse: collaboratorName}}
);
$('#collaboratorName').val("");
},
'click #remove-collaborator': function (event) {
var listedCollaborator = $('.js-listed-collaborator').val();
console.log(listedCollaborator);
Courses.update(
{_id: this._id },
{$pull: {canEditCourse: listedCollaborator}}
);
}
});
My MongoDB JSON:
{
"_id" : "j7A3tFdFBn5ECQGwe",
"title" : "Beatles",
"coverImageId" : "RERiadyMx8j8C9QQi",
"author" : "John",
"keywords" : [
"Paul"
],
"published" : "true",
"about" : "Testing the Course",
"canEditCourse" : [
"uo8SMdNroPGnxMoRg",
"FLhFJEczF4ak7CxqN",
"lkahdakjshdal",
"asödjaöslkdjalsöSA"
],
"createdById" : "uo8SMdNroPGnxMoRg",
"dateCreated" : ISODate("2015-12-28T16:30:34.714Z")
}
As seen in the JS-File, my final goal is to delete the clicked user from an array.
To get the text of the li item in the child link click event, combine the use of .parent() and .text() (since you can't use .val() on list items):
'click #remove-collaborator': function (event) {
console.log(event.target);
var listedCollaborator = $(event.currentTarget).parent().text();
console.log(listedCollaborator);
console.log(JSON.stringify(Template.parentData(0)));
Courses.update(
{
_id: Template.parentData(0)._id, /* or _id: Template.currentData()._id, */
canEditCourse: listedCollaborator
},
{ $pull: { canEditCourse: listedCollaborator } }
);
}
Notice you can use the current DOM element within the event bubbling phase through event.currentTarget to reference the element that kicked off the event. Since the element is the anchor tag, you get the li item as
its .parent(), and subsequently get its value with .text().
As for the update, use Template.parentData() to get the parent _id. Specify a parameter of 0 in the method which denotes the current data context level to look.
For example, Template.parentData(0) is equivalent to Template.currentData(). Template.parentData(2) is equivalent to {{../..}} in a template.
Since you've attached your event handler to the modalAddCollaborators template this will be the data context of that template which is nothing.
Just setup a nested template at the level you want to catch the event.
Furthermore with this pattern you can identify the _id of the collaborator directly, it will be this. The course _id however comes from the context of the parent template. (I'm not sure whether the course level data context is 1 or 2 levels higher however).
html:
{{#each canEditCourse}}
{{> nestedTemplate }}
{{/each}}
<template name="nestedTemplate">
<li class="list-group-item js-listed-collaborator">
{{this}}<a title="Remove Collaborator" id="remove-collaborator" class="btn btn-danger pull-right" href="#"><i class="fa fa-trash"></i></a>
</li>
</template>
js:
Template.nestedTemplate.events({
'click #remove-collaborator': function (event) {
Courses.update({_id: Template.parentData()._id },{$pull: {canEditCourse: this}});
}
});

Categories