Open a modal and fetch data from server on click of a button outside the component - vue.js

I am very new to Vue.js. In fact I just started today.
I have a problem.
Let's say I have button in a table somewhere in dom.
<table>
<tr><td><button v-on:click="showModal">Show</button>
</table>
Now I have a modal box outside of the scope of the button.
This button is inside a component of itself and the modal box has a component of itself too.
I am passing in an id with this button, and what I want to do is:
Fetch the id on button click
Show the record fetched in the modal and then finally perform some action on it
My problem is I am unable to get a method in the Modal component (that does a http request and fetches and renders the data) to trigger by the click event of this button.
The button and the modal has no relationship, they are not parent/child.

In modal component trigger method to fetch data by component ready state:
ready: function() {
this.getAllTheDataYouNeed();
},
You may use another life cycle hook:
https://vuejs.org/guide/instance.html#Lifecycle-Diagram

An option was to add the event broadcast in the common ancestor of both the components.
Like this:
var main = new Vue({
el: 'body',
components: {
zmodal : zmodal,
showhidebtn : showhidebtn,
},
methods: {
showModal: function (currentId) {
this.$broadcast('openModalBox', currentId);
}
}
});
Add an event listener in 'zmodal' and call this function showModal from on click event of 'showhidebtn' component.
It is working but now I have a set of codes outside the components that have to be triggered for this to work.
I wonder if there is a better way to do this.

Related

How do I trigger a click event using eventBus on vue?

New to Vue.js, trying to use the eventBus to emit events in different sibling components.
Here's the interaction I want to happen.
1. I click on a delete button on a card component.
2. A modal pops up asking to confirm the deletion.
3. User clicks OK in the modal to confirm deletion.
4. That click emits an event to the card component that triggers its delete method, finally deleting it.
My code is fine all the way to step 3 and then it just conks out.
I've been trying to use the eventBus but I'm not sure what I'm doing wrong. Here's my code starting from step 3.
props: {
jobs: { type: Array, default: null }
},
created(){
bus.$on('confirmGigDelete', () => {
console.log('running');
// What do I do here?
});
},
methods: {
deleteMyJob(id) {
console.log('this was deleted');
fetch(`${API_URL}/${id}`, {
method: "DELETE"
});
},
Is it possible to trigger confirmGigDelete this way in the HTML?
<img
:src="require('../../../assets/icons/common/deleteIcon.svg')"
id="deleteButton"
class="delete icon button"
#confirmGigDelete="deleteMyJob(job._uid)"
#click="showDeleteForm"
/>
You should avoid using the event bus in Vue as it is stated in the official documentation about dispatch and broadcast
It's better to use the event system for communication between child and parent. The child emits an event with this.$emit('event-name', payload) and the parent listens for events from its child with #event-name="myMethodInParent". This is just the good practice. The other good option is the use Vuex and to mutate state directly from child components.
Vue events docs
Vuex

Quasar Vue - How to call a method from dynamic loaded content from database

I have made a simple app using Quasar Framework - I load content from the database, and want to call a method on the component that opens a dialog. But I don't know how to do that, nothing happens.. What to do?
The button is rendered, but nothing happens when i click it.
Show video ( dynamic data loaded from the database ):
<button #click='showVideo()'>frea</button>
The showVideo() method exists on the component that loads and shows the button.
Data from VueX, using actions and getters
Action:
return axiosInstance.get('/program/' + id).then(res => {
commit(Mutation.SET_PROGRAM, res.data)
})
Component:
created:
this[ProgramAction.FETCH_PROGRAM](this.$route.params.id)
computed:
...mapGetters('program', ['program'])

Run method when Vuetify dialog is opened

I have a v-data-table and the user can click on any row and a dialog opens. Inside on my vuetify dialog is a dropdown of data.
I want to filter this data everytime the user clicks on a row and filter out what the user clicked from the dropdown inside the dialog.
Here is my dialog:
<v-dialog v-model="edit" max-width="1200" #input="closeDialog()">
<editCompany :isEdit="true"
v-if="showEdit"
:company="selected"
:adminEdit="true"></editCompany>
</v-dialog>
You can see I'm passing in the values from the table row the user clicked.
Now, I need to use the value being passed in to filter the dropdown. The mounted event only runs once, so my logic inside of it only fires for the first row clicked.
Here is the mounted event inside of my editCompany template:
mounted: async function () {
this.filterOutResults(); //this is where i do my filtering and it works
},
Every other row the user clicks doesn't fire mounted, so I cant use that unless I can unmount the dialog when its closed.
I found how to fire an event when the dialog closes, but I cannot find a vuetify open event.
How do I run a function everytime the dialog opens so I can filter the results or how do I unmount the dialog everytime it closes, so the mounted event can run everytime? Thanks
For future references, I'll expand #mynd comment, which should be the answer:
export default {
data() {
return {
dialogVisible: false,
},
},
watch: {
dialogVisible(visible) {
if (visible) {
// Here you would put something to happen when dialog opens up
console.log("Dialog was opened!")
} else {
console.log("Dialog was closed!")
}
}
},
<v-dialog v-model="dialogVisible" max-width="1200" #input="closeDialog()">
<!-- Add code here, according to Vuetify docs -->
</v-dialog>
For further information (about constructing the v-dialog component itself), refer to the official docs
if you want to do something inside the dialog component when it's open, there is a little workaround that you can do.
<v-dialog v-model="edit" max-width="1200" #input="closeDialog()">
<editCompany :isEdit="true"
v-if="showEdit"
:company="selected"
:dialogOpen="edit"
:adminEdit="true"></editCompany>
</v-dialog>
as you see you can pass dialog's handler variable as dialog's parameter. its 'dialogOpen' in this case.
then inside editCompany component,
watch: {
'dialogOpen' :{
handler(newVal, oldVal) {
//do your stuff.
},
deep: true
},
}
So in short it will watch the variable which is controlling dialog, based on its value which mostly is true or false, you can do your operation.

Vue.js: Only load component if user clicks button

I have code that looks like the code below. how do I set this up so the components "dataPart1' and "dataPart2" won't load unless a user clicks a button to view the data? In other words, I don't want the data to just automatically show, but only if the user chooses to see it via a button click option.
var app = new Vue({
el: '#data',
data: {
show: true,
something: true,
},
components: {
dataPart1,
dataPart2
},
...other stuff...
}
});
In order to conditionally display content in the templates (text, html, components, etc), we can use conditional rendering of Vue.js and specifically v-if directive.
Short explanation: we can display content depending on certain variables defined in our component. And change value of that variable on certain events, e.g. button click.
Please, take a look at example on CodeSandbox of loading two components conditionally on buttons clicks.
In App.vue file, we have 2 buttons that trigger a handler on click and display component's if corresponding value is true.

vue: design a dynamic "window" component like bootstrap modal

I am trying to create a generic HTML Window from Vue application.
What I want
I click "edit" on item from list, a DHTML popup will be opened with a Vue component inside. I can click Save or close the opened component need to removed from the page and may the caller recive a event/promise with resolve (Save) or reject (Close).
What I am tried
I was started via DOM:
function Win(vueapp,obj) {
var div = document.createElement("div");
var Win = JQueryOldFunction()
//need a way to resolve when the user hit 'Save' and reject when closing
var resolve,reject, promise = new Promise(function(a, b) {
resolve=a, reject=b;
});
new Vue({
el: div,
data: {data:obj} //need a way to pass it to the component
render: function (h) {
return h("m");
},
components: {
'm': httpVueLoader(vueapp+'.vue') // this from https://github.com/FranckFreiburger/http-vue-loader
}
});
return promise;
}
This is working, but I can't use Vue to destroy the window after clicking save, and can't pass objects inside
so I was tried other option:
<component :is="gui.window" transition="fade" transition-mode="out-in"></component>
Model.gui.window='EditGroup'
(took from here: https://coligo.io/dynamic-components-in-vuejs/ )
This is better, it working, does not allowing more than one window, but the internal component can't destroy itself.