I have a VueJS project - which in one view there are parent and child components that are both using the same component called deleteModal.
When I trigger the modal from the child (to show it), it triggers both the child and parent modals (except no data is passed to the modal triggered by the parent). As I understand it, this is because I have used the component twice - in the parent and child - example below. To note, it works as expected from the paren
I've researched and tried a few things: setting a key value for each of the components, changing the components ref name among other things. I have also tried using v-show to only show component just before I trigger the parent model however, this solution is not ideal.
How can I only trigger the modal from the child?
Parent Component
<template>
<div>
<childCompt ref="childCompt" />
<deleteModal
ref="deleteModal"
#deleteTriggerAPI="deleteAPIParent"
/>
</div>
<template>
Child Component - childCompt
<template>
<div>
<deleteModal
ref="deleteModal"
#deleteTriggerAPI="deleteAPIChild"
/>
</div>
<template>
My old answear is not good at all. I personally to show and hide element using jquery in vue. For me right now this is best solution but maybe i don't know some best.
If you want use only vue i using also variable passing to child from parent which will support visable of your modal.
We pass variable with ":" and register event with "#".
<template>
<childComponent :isModalOpen="isModalOpen" #onModalClose="isModalOpen=false">
<template>
export default {
name:"parent",
data: () => {
isModalOpen: false
}
}
In child we catch this by using props. We need to define type of varialbe we pass. Different between props and data is that in props we cannot change value in child component.
export default {
name: "child",
props: {
isModalOpen: Boolean
}
}
And you can use this variable to show or hide modal. Also in child component we can create button to close modal and we emit event to parent in order to change variable value.
To do this we using this.$emit('eventName');
More information right here: https://forum.vuejs.org/t/passing-data-back-to-parent/1201
You could try globally defining the component,
ie, in main.js
Vue.component('deleteModal',deleteModal)
Related
I created a custom alert component using Vue 3 with Vuetify 3 with two root nodes
<template>
<v-alert type="warning" title="Contains button to display dialog" />
<v-dialog>dialog goes here</v-dialog>
</template>
The v-alert component contains a button to toggle the state of the v-dialog component.
In my parent component ( the consuming one ) I would like to apply a CSS class to the child component ( my custom alert component )
<MyAlert class="mb-8" />
<div>Main content goes here</div>
The problem is that this doesn't work, I get the warning
[Vue warn]: Extraneous non-props attributes (class) were passed to component but could not be automatically inherited because component renders fragment or text root nodes
Which makes sense because it doesn't know which component should have this class, both, either alert or dialog or none.
A quick fix would be to apply the class mt-8 to the div below. But my alert component is conditional so I would have to use an if-statement to check if I should apply a margin-top or not.
Reproduction link: https://play.vuetifyjs.com/#eNp9UstuwjAQ/BXLFy4krvpShVIE4swXYA4hGHCJH7I3QRHKv3cdB0ih7SmZnfXseD2rM51bm9aVoBOagVC2zEFMuSYkq5Pc2u63AyqXukeIl828FA5IUebef3KqNskHp4TdOrayni7xDCmMBqGB7I3w5CCcyFjgemE2UA4gzszYwAtCXzhpgXgBVaClsgaHn4kTO9KSnTOKjPASoyt18ReplC0OstyGe2JLxqIcCtExjQfQhE2/vNG4h3PwwnvCczohXSXUUCBgTg8A1k8Yq7Q97tPCKDZDjrlKg1Qi2Ro1e0mf09c3vKuHYT0VXiUbZ05eOJzI6XggDnLX/DWgp1H3KX2Psn0pSD5IMdSvhUuc0FtcuvvX913vD+933IP/MLPlusVdllIf/d0aC9+tcLWOLdeH+DVw3ZtBYwVG6pQ7LfUeUwUSylBZYJIwK55sKgCjCRiCDlGhwW9emtAbE4hasdLHLIJbBC9puzYNAkfbMY33R7vdsun6G20jDc0=
Is it possible to tell Vue it should use the applied class for the inner v-alert component?
So, you are trying to assign classes to a component, but your component contains fragments.
Wrap your Child.vue component tags:
<template>
<div>
<v-alert type="warning" title="Contains button to display dialog" />
<v-dialog>
dialog goes here
</v-dialog>
</div>
</template>
Yes you can!
First thing you need to do is to specify the
inheritAttrs: false
option in your alert component:
<script>
export default {
inheritAttrs: false,
}
</script>
and than you can apply class attribute to the desired component using
:class="$attrs.class"
But you must know, that now every other attribute must be specified in code using $attrs, because your component would not apply them by default anymore
More on this topic can be found here Vue Docs
I have a callback function which receives an argument from child component(here CardTiles) and it is processed and passed as props to another child component. The output is displayed correctly but I have to move my page to that particular section(the second child component-OutputWindow). How can i trigger an anchor tag from my 1st child component? or would refs work here?
Child component 1:
<CardTiles parentCallback={handleCallback}/>
Child component 2:
<OutputWindow name={place}/>
or would refs work here
Yes. Have a ref in the parent, put it on the child (ref={theRef}), have the child forward that ref to the outermost (probably) HTML element it renders, and then in the callback function have the code use theRef.current?.scrollIntoView()¹ to scroll that element into view.
More
Refs
Forwarding refs
scrollIntoView
¹ That's using optional chaining, which is fairly new. If your project isn't set up for it, you can use if (theRef.current) { theRef.current.scrollIntoView(); } instead.
I have the following template in a specific modal component:
<template>
<my-base-modal ref="BaseModal" :width="1000">
<template v-slot:header>Details</template>
<template v-slot:body>
<detail-card ref="DetailCard"></detail-card>
</template>
</my-base-modal>
</template>
It creates a base modal and overwrites the slots for header and body.
The body slot is filled with a sub component which needs to load some data.
I tried to use the following method to open and load the content of this modal:
open (id) {
this.$refs.DetailCard.load(id)
this.$nextTick(() => {
this.$refs.BaseModal.open()
})
}
But this.$refs.DetailCard is always undefined. I suspect this is because the reference DetailCard is defined inside the body slot of the <base-modal> component?
How am I supposed to trigger a function on the <detail-card> component in this example, without using EventBus or passing some props into it?
My suspicion is that at runtime, the DOM is not rendered until the BaseModal's open method is invoked. Therefore, this.$refs.DetailCard will returned undefined since the body slot of your component has not rendered with the nested component.
As you have mentioned in the comments, the fix can be as easy as ensuring that the DOM is already rendered, e.g. using v-show instead of v-if.
I'm writing a React application with a lot of modals (but only one ever active at a time with no nested modals), and I'm unsure of which of these two solutions is preferable when it comes to handling showing and hiding these modals:
Have a state boolean variable in the parent component that determines whether or not the modal should be shown. If this boolean variable is false, don't render the component. If it's true, render it. Allow the modal to influence this event via a passed in props callback it can leverage. Example snippets:
{ this.state.prompt === "makePW" ?
<MakePassword closeModal={this.closePWModal} /> :
null
}
Now, within the component, it is always visible and does not control its lifecycle. If it is being rendered then it is visible.
Just always show the component in the parent component, like so:
<MakePassword />
Then within the component itself handle its entire lifecycle. That is, the component will have a boolean state variable for its visibility. Some snippets for this approach:
<Modal open={this.state.open} onClose={this.closeModal}>
<Modal.Header>Header</Modal.Header>
<Modal.Content>Body</Modal.Content>
</Modal>
There are also hybrid approaches, and other solutions as well I'm sure.
Regardless, I suppose the essence of my question is wondering about the preferable solution for showing and hiding modals: is it to always render them and just toggle their visibility, or to actually toggle between adding and removing them from the DOM? And, should the modal itself generally control its lifecycle or should the parent?
i prefer 1st one but if you want to use the second , i would extend the makepassword component from PureComponent to optimize your component.
Instead of writing shouldComponentUpdate() by hand, you can inherit from React.PureComponent. It is equivalent to implementing shouldComponentUpdate() with a shallow comparison of current and previous props and state. - source react docs
class MakePassword extends React.PureComponent{
...
}
I think it depends on your application.
For example, React-Bootstrap modals stay in the DOM and that allows for nice in/out animations.
How to target method inside other component?
I'm working on a project where I want to target a method inside another component. I press a button inside the dashboard component and I want to change the data inside my line-chart component (which uses vue-chartjs). How can I target this method?
Well you could target it over $refs however, this is pretty dirty, as it prodvides a pretty strict binding of your componentes.
A better solution would be to trigger an event (eventbus) or over an prop.
You can call children's method by referencing them through refs
In your example, your dashboard's template should looks like this :
<template>
<div>
<button #click="$refs.chart.yourMethod()">Call child method</button>
<line-chart ref="chart"></line-chart>
</div>
</template>