I basically import 2-3 components in a parent component and based on the button clicks I simply hide and show some components. In every component I have Back and Next buttons, when they clicked, I show different components in different situations. Here's a simple example of one my components;
<template>
<div>
<transition name="fade" appear>
<div class="justify-center">
<form #submit.prevent="submitFormTest" v-if="!back && !configuration">
Bunch of code here is irrelevant with my question...
<!-- Buttons -->
<div class="text-center mt-4">
<button #click="back = true" class="btn-w-orange mr-2" type="button">Back</button>
<button #click="nextButton" class="btn-w-orange" type="button">Next</button>
</div>
</form>
<modalOpMode v-if="back"></modalOpMode>
<modalConnection v-if="configuration && !back"></modalConnection >
</div>
</transition>
</div>
</template>
and here is my script;
<script>
import modalConnection from "./modalConnection";
import modalOpMode from "./modalOpMode "
export default {
data(){
return {
configuration: false,
back: false
}
},
components: {
modalOpMode,
modalConnection,
},
methods: {
nextButton(){
this.configuration = true;
},
},
}
</script>
I statically imported two other components to display when back and next button is clicked. Everything is okay when I go for Next button for ALL MY COMPONENTS. (There are other components that I get the same error.). But the problem occurs when I click the back button. When Next is clicked, the form is hidden and modalConnection is visible as it should but when Back is clicked, I only see a blank page because the modalOpMode gives me the following error;
[Vue warn]: Unknown custom element: <modalOpMode> - did you register the component correctly? For recursive components, make sure to provide the "name" option.
I'm pretty sure that I import the component in the correct way, the path, the component name, the usage, everything is normal because I do that with the other one modalConnection and that one works all good. If you want to check my modalOpMode component, here it is;
<template>
<transition name="fade" appear>
<div>
<form #submit.prevent="submitFormTest" v-if="configuration == ''">
There are four radio buttons that bound with v-model to change the value of configuration variable
</form>
<!-- Modal Comp1-->
<modalComp1 v-if="configuration == 'comp1'"></modalComp1>
<!-- Modal Comp2 -->
<modalComp2 v-if="configuration == 'comp2'"></modalComp2>
<!-- Modal Comp3-->
<modalComp3 v-if="configuration == 'comp3'"></modalComp3>
<!-- Modal Comp4 -->
<modalComp4 v-if="configuration == 'comp4'"></modalComp4 >
</div>
</transition>
</template>
In here I imported 4 other components and bound them to a variable called configuration. When the variable is equal to something like comp1 or comp2 as above, I simply display the relevant component and hide the other content.
As I said before, when I click the next button and show the components, it's all good, but I can't go back, it gives me the above error. What am I doing wrong or what am I missing here? Thanks in advance
In Components you have modalOperatingMode instead of modalOpMode
Related
This is the first time I am using modal component. Inside a for loop of an array of objects, I also added a modal component, "Add Item". The v:onClick="showSectionID" function in the SHOW button within the modal should just consolelog the id of the object who's associated modal was opened and click it's respective SHOW button. But instead it is giving the id of the last object wherever I click the SHOW button from any of associated modals.
Just to test, I removed the whole modal and only kept the SHOW button and in this case it gives me the correct id. I really cannot figure out what s is wrong in the modal and searched several sources in the internet to see a similar solution but couldn't find. See code:
<div v-for="(section) in allDataObject['Section']" :key="section['uuid']">
<h4>Section Name: {{ section["sectionName"] }}</h4>
<h4>Section Description: {{ section["sectionDescription"] }}</h4>
<template>
<div>
<b-button #click="modalShow = !modalShow">Add Item</b-button>
<b-modal v-model="modalShow">Fill form to add an item !
<button v-on:click="showSectionID (section['uuid'])">SHOW</button>
</b-modal>
</div>
</template>
</div>
In your code, you are creating a modal component for each section within the for loop.
I wouldn't be surprised if actually all your modals show up on the screen, but you see the last one because it's on top of all the other ones. But it also depends on how the modal is implemented.
I suggest you to move the modal template outside your for loop and change what you store in your component data so that you know which section to show in the modal.
Let's say your data() will look like this:
data() {
return {
modalVisible: false,
modalSectionUUID: null
}
}
Then you can create two methods to show and hide the modal:
methods: {
showModal(sectionUUID) {
this.modalVisible = true;
this.modalSectionUUID = sectionUUID;
},
hideModal() {
this.modalVisible = false;
this.modalSectionUUID = null;
}
}
Now, your template will finally look something like this:
<b-modal v-model="modalVisible">Fill form to add an item !
<button v-on:click="showSectionID(modalSectionUUID)">SHOW</button>
</b-modal>
<div v-for="(section) in allDataObject['Section']" :key="section['uuid']">
<h4>Section Name: {{ section["sectionName"] }}</h4>
<h4>Section Description: {{ section["sectionDescription"] }}</h4>
<template>
<div>
<b-button #click="showModal(section['uuid'])">Add Item</b-button>
</div>
</template>
</div>
I have a setup in a Vue-powered UI, where the user can toggle the contents of a certain div between several options, and two of those options happen to be instances of the same child component (with different properties passed in).
Everything works fine when displaying any given content page for the first time, or when toggling between two unrelated content pages. However when toggling between the two pages which both use the same child component, the div content doesn't get updated.
In code it looks (greatly simplified) like this:
Parent component
<template>
<div>
<!-- toggle buttons -->
<div class="page-button" #click="page=1">About</div>
<div class="page-button" #click="page=2">Dog List</div>
<div class="page-button" #click="page=3">Cat List</div>
<!-- page content -->
<div v-if="page===1">some plaintext here...</div>
<div v-if="page===2">
<childComponent :state="state" listName="dogs" />
</div>
<div v-if="page===3">
<childComponent :state="state" listName="cats" />
</div>
<!-- rest of file omitted -->
childComponent.vue
<template>
<div>
<template v-for="(item, index) in items">
<div>{{ index }}: {{ item.label }}</div>
<!-- etc.. -->
</template>
</div>
</template>
<script>
module.exports = {
props: ['state', 'listName'],
data: function () {
return {
items: this.state.lists[this.listName],
}
},
}
</script>
In the above, state is a global state object that all components have access to, with state.lists.dogs and state.lists.cats being regular arrays.
When the UI initializes with page set to 2 or 3, everything works correctly - the dog list shows for page 2, and the cat list shows for page 3. Likewise, when I click page 2, then page 1, then page 3, everything is fine. However when toggling back and forth between page 2/3, the vue doesn't re-render the child component.
I assume it's possible to work around this by changing the underlying data structure or by binding the child component differently. But is there a straightforward way to make Vue re-render the component as expected?
I guess what you see is Vue trying to optimize rendering by reusing existing component instance. Add key attribute on your childComponent with different values...
<!-- page content -->
<div v-if="page===1">some plaintext here...</div>
<div v-if="page===2">
<childComponent :state="state" listName="dogs" key="dogs" />
</div>
<div v-if="page===3">
<childComponent :state="state" listName="cats" key="cats" />
</div>
<!-- rest of file omitted -->
Other solution (and much better IMHO) is to make your component "reactive" to prop changes - instead of using props to initialize the data() (which is "one time" thing - data() is executed only once when component is created), use computed
module.exports = {
props: ['state', 'listName'],
computed: {
items() {
return this.state.lists[this.listName]
}
},
}
You can use v-show if you just want to render it before hand. Its more costly but it should work without any issues.
<template>
<div>
<!-- toggle buttons -->
<div class="page-button" #click="page=1">About</div>
<div class="page-button" #click="page=2">Dog List</div>
<div class="page-button" #click="page=3">Cat List</div>
<!-- page content -->
<div v-show="page===1">some plaintext here...</div>
<div v-show="page===2">
<childComponent :state="state" listName="dogs" />
</div>
<div v-show="page===3">
<childComponent :state="state" listName="cats" />
</div>
<!-- rest of file omitted -->
I am using popover from Bootstrap-Vue, and I get this error:
[BootstrapVue warn]: popover - Unable to find target element in
document.
Everything work just fine, but I have a lot of warnings and I want to fix them.
Parent Component
<template>
<popover />
<label id="popover-target-EXAMPLE">
<i class="far fa-question-circle"></i> Parish
</label>
</template>
<script>
import Popover from './Popover';
export default {
components:{
Popover,
}
}
</script>
My popover Child Component
<template>
<div>
<b-popover target="popover-target-EXAMPLE" variant="primary" triggers="hover" placement="top">
<p class="popover-style">TEXT</p>
</b-popover>
//here are multiple <b-popover>....
</div>
<template>
Try to put the popover component after the targeted element
After some time I found out the problem.
In that Popover child I had multiple popovers, and some of them are not in parent component.
So to fix the warnings I removed all <b-popover> that don't have an ID in parent component.
I have 1 page with 2 components. Component A has a button, when clicking disalbe A and show component B.
If i use transition i am getting this error.
I want a nice fadeout A and fade in B, how can i achieve?
Error:
[Vue warn]: <transition> can only be used on a single element. Use <transition-group> for lists.
App.js
<transition name="fade">
<div class="fade-enter-active" v-show="datatable">
<component-a :title="'AAA'"></component-a>
<button v-on:click="showCompB">Show B and disable A</button>
</div>
<div class="fade-enter-active" v-show="componentb">
<component-b :title="'BBB'"></component-b>
</div>
</transition>
export default {
data() {
return {
datatable: true,
componentb: false,
etc etc
Good morning sir,
As the error stated, the <transition> component can be used only with a single child element. You can learn more about that here: https://v2.vuejs.org/v2/guide/transitions.html
You could instead use two <transition> components to handle the fade animation for each one of your elements like so:
<transition name="fade">
<div v-show="datatable">
<component-a :title="'AAA'"></component-a>
<button v-on:click="showCompB">Show B and disable A</button>
</div>
</transition>
<transition name="fade">
<div v-show="componentb">
<component-b :title="'BBB'"></component-b>
</div>
</transition>
The fade animation will be applied to each div whenever componentb and datatable is visible or not.
Hope that helps you.
As per example given in aurelia documentation I am opening dialog box with viewmodel (say prompt ). This prompt has view inside in which I am adding "router-view" tag.
My routes are already configured. So when first time I open dialog it opens correct views as configured in routes and everything works well. But when I close dialog and re-opens dialog, It's not showing first route view. If I click other route link and come back to first route it works.
I have observed it's not creating instance of view model of first route( when opened dialog second time).
How to fix this issue?
Prompt html
<template><div class="row">
<left-menu ></left-menu>
<router-view></router-view>
</div></template>
<template>
and left-menu.htm
<template>
<div class="list-group">
<template repeat.for="item of items">
<a class="list-group-item ${$parent.selectedNav === item.routeName ? 'active' : ''}" route-href="route.bind: item.routeName;" click.delegate="$parent.select(item)">${item.text}</a>
</template>
</div>
Using a router inside a modal window seems off to me. The router is used to manage pages, but a modal is used to manage content within a page.
I would suggest building a modal window component, you can use <slot> tags to inject content and set it's model bindings to any data within the current view model.
Here's an example of my component that I use for this.
<template>
<div show.bind="visibility" class="modal-window">
<div>
<button class="btn btn-danger btn-sm close-button" click.delegate="close()">close</button>
</div>
<slot></slot>
</div>
<div show.bind="visibility" class="modal-window-overlay" click.delegate="close()"></div>
</template>
-
import { bindable } from 'aurelia-framework';
export class ModalContent {
#bindable visibility: boolean;
close(){
this.visibility = false;
}
}
<modal-content id.bind="'add-variant-window'">
<h4>Modal Content</h4>
<div>you can bind this to things on the current viewmodel</div>
</modal-content>