why child component getting instantiated more num of times than needed when used by 2 different components? - dynamic

I am trying to instantiate child component on click of a button in parent component. This same child component need to get instantiated on click of 2 more buttons in a different component. This child component is nothing but a modal component and basically modal component needs to get instantiated from 2 different components(one in header, another in parent). I have a modal template in which modal data comes dynamically. I am instantiating modal component using dynamic component loader. Now modal component is getting instantiated when buttons are clicked. But they are instantiated more times than expected.
Below is header html where click of one button is happening:
<-- code here-->
<!-- FAQModal -->
<modal-component #modalID></modal-component> // modal-component is selector of modal.html
<-- code here-->
<li [style.display]="!showFAQ?'none':'inherit'"><a (click)="getFAQ()" data-remote="false"
data-toggle="modal" data-target="#modalTarget"><i class="fa fa-question"></i>FAQ</a></li>
header.component.ts -
getFAQ() {
this._modalService.setModalId('FAQ');
if (this.component !== undefined) {
this.component.then((componentRef: ComponentRef) => {
componentRef.dispose();
return componentRef;
});
}
this.component = this.dcl.loadIntoLocation(ModalComponent, this._elementRef, 'modalID');
}
parent.html
<!-- Modal -->
<div #modalID></div>
<div class="col-sm-12 btnpolicymargin">
<a (click)="getTerms()" data-remote="false" data-toggle="modal" data-target="#modalTarget" class="tosModal">Terms and Conditions</a>
<a (click)="getPolicy()" data-remote="false" data-toggle="modal" data-target="#modalTarget" class="pcModal">Parent Consent Policy</a>
</div>
parentcomponent.ts - below piece of code in parent component
getTerms() {
this._modalService.setModalId('T&C');
this.instantiateModalComponent();
}
getPolicy() {
this._modalService.setModalId('ParentPolicy');
this.instantiateModalComponent();
}
instantiateModalComponent() {
if (this.component !== undefined) {
this.component.then((componentRef: ComponentRef) => {
componentRef.dispose();
return componentRef;
});
}
this.component = this.dcl.loadIntoLocation(ModalComponent, this._elementRef, 'modalID');
}
Modal template
<div id="modalTarget" 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">{{modalTitle}}</h4>
</div>
<div class="modal-body">
<div [innerHTML]="modalData"></div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
ModalComponent
constructor(private _modalService:ModalService) {
this._modalService.updateModalId.subscribe(modalId => {
this.modalID = modalId;
console.log('id:' + this.modalID);
switch (this.modalID) {
case 'FAQ':
this.goFAQ();
break;
case 'T&C':
this.getTerms();
break;
case 'ParentPolicy':
this.getPolicy();
break;
default:
break;
}
});
}
goFAQ() {
this._modalService.goFAQ().subscribe(data => {
this.modalData = data;
this.modalTitle = 'Frequently Asked Questions';
});
}
Modal service is used to set modalId which indicates which button is pressed. Also when setting an event emitter is used to pass data to other components.
Can somebody help me to understand what could be the issue? why modal component getting instantiated more number of times and calling backend more than needed.?is it because modal is getting used by 2 different components?

Related

Vuejs shows the same data on multiple components

I have the following component chain in my project (templates are in different vue files, here ... acts as a separator to make it readable):
<!-- Sensors template -->
<div class="container">
<div class= "sensors_item">
<SensorItem v-for="i in sensors" :sensordata="i" :key="sensors.id"></SensorItem>
</div>
</div>
...
<!-- SensorItem template -->
<div>
<SensorParameterItem v-for="i in sensordata.sensorparams" :parameterdata="i" :key="sensordata.sensorparams.id"></SensorParameterItem>
</div>
...
<!-- SensorParameterItem template -->
<div class="col parameter-icon-clickable" v-on:click="openChart">
<i class="fas fa-chart-line" color="white"></i>
</div>
</div>
<ChartCollapsible class="parameter-icon-clickable" :isOpen="isChartOpen" :pdata="parameterdata"/>
</div
...
<!-- ChartCollapsible template-->
<div>
<transition appear name="modal">
<div v-if="isOpen">
<div class="chart-container">
<apexcharts height="400" width="100%" ref="chart" type="area" :options="o1" :series="setSeries"></apexcharts>
<!-- OK -->
</div>
</div>
</transition>
</div>
...
Functions
...
openChart: function() {
let data = {count: 144};
console.log('openChart');
this.$store.dispatch('getsensordata', data)
this.isChartOpen = !this.isChartOpen;
}
...
computed: {
setSeries() {
console.log("Computed.")
if(this.$store.getters.authStatus == "received") {
this.s1 = _.cloneDeep(this.$store.getters.getData);
} else {
this.s1 = _.cloneDeep([{data: [{x:0,y:0}]}]);
}
return this.s1;
}
}
I'm calling the backend by clicking in the SensorParameterItem (openChart fn) to receive chart data. Then, in ChartCollapsible I have computed which verifies that new data is received. After that it deep copies the new data into a property and returns that property to the chart component. I'd expect that each ChartCollapsible component would have its own chart data but it's not: I have 10 ChartCollapsibles rendered and all is updated with the same data, when I click any openchart button.
Any help would be great how to solve this issue!
Okay I've found what caused this behaviour: there is a computed property in the component, which monitors this.$store.getters.authStatus == "received" state. Since ALL component instances monitor this single state, when it changes, ALL component instances will be updated.
A possible fix is to send some component specific data (title, id, etc.) along this.$store.dispatch('getsensordata', data) request which will be replied back to all component instances, but only one component will be updated:
computed: {
setSeries() {
if(this.$store.getters.authStatus == "received") {
// Filter down to our chart otherwise all charts will be updated!
if(this.header.title == this.$store.getters.getData.header.title && this.parameterdata.pidx == this.$store.getters.getData.header.pidx) {
this.s1 = _.cloneDeep(this.$store.getters.getData.data);
}
}
return this.s1;
}
}

Vue.js 2.6.12 with Bootstrap 5.1.0 - Issue with manual component initiation

Following up on my old thread Vue.js (2.x) with Bootstrap 5
I keep having issues when creating a bootstrap component wrapper in Vue.
The idea is to create a wrapper for each Bootstrap component that I want to use (not all of them).
The issue happened when I tried to create a bootstrap.Dropdown wrapper. The dropdown menu is shown properly when clicked, but it didn't auto-close when clicking outside (somewhere else).
<template>
<div ref="el" class="dropdown">
<button
class="btn btn-primary dropdown-toggle"
type="button"
data-bs-toggle="dropdown"
aria-expanded="false"
>
Select...
</button>
<ul class="dropdown-menu">
<slot></slot>
</ul>
</div>
</template>
<script>
import { Dropdown } from 'bootstrap';
export default {
name: 'BootstrapDropdown',
data() {
return {
dropdown: null,
};
},
mounted() {
const { el } = this.$refs;
this.dropdown = new Dropdown(el, {
autoClose: true,
});
['show', 'shown', 'hide', 'hidden'].forEach((e) => {
el.addEventListener(`${e}.bs.dropdown`, () => {
this.$emit(e);
});
});
},
};
</script>
Any ideas are welcomed. Thanks in advance.
I think it's not working because the Dropdown instance needs to be set on the trigger element, not the container. Change the "el" ref to the trigger button...
<template>
<div class="dropdown">
<button
ref="el"
class="btn btn-primary dropdown-toggle"
type="button"
data-bs-toggle="dropdown"
aria-expanded="false"
>
Select...
</button>
<ul class="dropdown-menu">
<slot></slot>
</ul>
</div>
</template>
Demo

bootstrap 4 modal doesn't open at first click using vue js

My bootstrap 4 modal doesn't show up when I press on my button, but my computed property is for triggered(from the console)
Here is my template code
<form>
<!-- button that triggers the modal -->
<div id="btnBereken">
<a
class="btn btn-success btn-lg"
data-target="#exampleModal"
v-on:click="Vali"
v-bind:data-toggle="Validation"
>Bereken</a>
</div>
</div>
</form>
<!--modal itself-->
<div
class="modal fade"
id="exampleModal"
tabindex="-1"
role="dialog"
aria-labelledby="exampleModalLabel"
aria-hidden="true"
v-show="Ok"
></div>
Here is my script code I have one method and one computed property that is linked to data-toggle of my button
Vali: async function(){
this.Ok =true;
}
and my computed property
Validation() {
if (this.Ok) {
console.log("getriggerd");
return "modal";
}
}
When I press on my button once it the pop doesn't trigger but the second time it does, and my value for this.Ok gets updated on my console and in VueJS dev tool

how to fix jquery error "Uncaught TypeError: Cannot read property 'style' of undefined" for blue-imp gallery in modal Bootstrap?

I used bootstrap 3 and blueimp-gallery in a web html5. My problem is a carousel-gallery dont show images and receive a error in a console "Uncaught TypeError: Cannot read property 'style' of undefined" when i use a blueimp-gallery-carousel in a modal div, but if i enter in a developer tools for chrome, this error disappears, and the images show in carousel-gallery.
The code.
<!-- Portfolio Modals -->
<!-- Use the modals below to showcase details about your portfolio projects! -->
<!-- Portfolio Modal 1 -->
<div class="portfolio-modal modal fade" id="portfolioModal1" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-content">
<div class="close-modal" data-dismiss="modal">
<div class="lr">
<div class="rl">
</div>
</div>
</div>
<div class="container">
<div class="row">
<div class="col-lg-8 col-lg-offset-2">
<div class="modal-body">
<h2>Vinilos</h2>
<div id="links">
1
2
3
</div>
<div id="blueimp-gallery-carousel" class="blueimp-gallery blueimp-gallery-carousel blueimp-gallery-controls">
<div class="slides"></div>
<h3 class="title"></h3>
<a class="prev">‹</a>
<a class="next">›</a>
<a class="play-pause"></a>
<ol class="indicator"></ol>
</div>
<p>Vinilos para rotulacion, decorativos, efecto espejo, fibra de carbono, refractivos, hologramas y farolas</p>
<button type="button" class="btn btn-primary" data-dismiss="modal"><i class="fa fa-times"></i> Cerrar Producto</button>
</div>
</div>
</div>
</div>
</div>
</div>
and my javascript
<script>
document.getElementById('links').onclick = function (event) {
event = event || window.event;
var target = event.target || event.srcElement,
link = target.src ? target.parentNode : target,
options = {index: link, event: event},
links = this.getElementsByTagName('a');
blueimp.Gallery(links, options);
};
</script>
<script>
blueimp.Gallery(
document.getElementById('links').getElementsByTagName('a'),
{
container: '#blueimp-gallery-carousel',
carousel: true,
}
);
</script>
and the link web problem
http://www.colombiawaterprint.com/web/index3.html
How i Solve this error?
I believe your problem is that your blueimp gallery is initially hidden as it is in a Bootstrap Modal. As such, when you first initialize the gallery it can't find the gallery. I think all you need to do is wait for the Bootstrap modal to be shown and then initialize the gallery.
Bootstrap triggers an event that you can listen for for this very purpose - http://getbootstrap.com/javascript/#modals-events - You probably want the shown.bs.modal event.
You would use it something like this. (assuming jQuery is loaded)
$('#portfolioModal1').on('shown.bs.modal', function (e) {
blueimp.Gallery(
document.getElementById('links').getElementsByTagName('a'),
{
container: '#blueimp-gallery-carousel',
carousel: true,
}
);
})
Bear in mind this is untested code and may not 'just work'. But hopefully you get the idea. You also may want to do a test to see if you've already initialized the gallery, as it stands this would re-initialize it every time the shown.bs.modal event was fired.

How to use dynamic component loader to instantiate a child component on a click?

I am using angular2.0.0-beta.15. Basically I am trying to load a modal window on click of a button in header. I have put template for modal in an html.What I am trying is, on click of button in parent component, a parameter which indicates which button is pressed, is passed to child component. Based on that I am getting data of modal from db and putting that in modal window.Below is the piece of code.
parent.html
<modal-child id="ContactModal"></modal-child>
<-- code goes here-->
<li [style.display]="!showContact?'none':'inherit'"><a (click)="getContact()" data-remote="false"
data-toggle="modal" data-target="#ContactModal"><i class="fa fa-question"></i>Contact</a></li>
<-- code goes here-->
parent.component.ts
import {Component, Input, provide, DynamicComponentLoader, Injector} from 'angular2/core';
import {ModalChildComponent} from './modal.child.component';
export class ParentComponent{
private id: string;
constructor(private dcl: DynamicComponentLoader, private injector: Injector) {}
getContact() {
this.id = 'Contact';
this.dcl.loadAsRoot(ModalChildComponent, '#ContactModal', this.injector);
}
}
modal.child.component
import {Component, Input} from 'angular2/core';
import {UserService} from '../services/data-services.service';
#Component({
selector: 'modal-child',
templateUrl: './views/templates/modalTemplate.html'
})
export class ModalComponent {
#Input('id') modalId: string;
private contactData: string;
constructor(private _dataService: DataService) {
console.log('id:' + this.modalId);
if (this.modalId === 'Contact') {
this.getContactData();
}
}
getContactData() {
this._dataService.getContact().subscribe(data => {
console.log('contact:' + data);
this.contactData = data;
});
}
}
modalTemplate.html
<!-- Contact -->
<div id="ContactModal" 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">Contact</h4>
</div>
<div class="modal-body">
<div [innerHTML]="contactData"></div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
When i try above code, it gives me exception like 'Unexpected directive value '[object Object]' on the View of component 'ParentComponent'. Can somebody guide me?