How do I get one constructor to fire multiple tooltips? - tippyjs

I am trying to get one button to fire multiple tippy elements at once. I have created a each of the tippy() instances, but it does not work.
<span class="btn btn-success show-tooltip">test</span>
<span class="test-one" data-tippy-content="This is tooltip">Text</span>
<span class="test-two" data-tippy-content="This is another tooltip">Text</span>
<script>
tippy('.test-one', {
triggerTarget: '.show-tooltip'
});
tippy('.test-two', {
triggerTarget: '.show-tooltip'
});
</script>
But doing so doesn't fire the tooltip.

Related

How to programatically control Bootstrap 5 components in Vue 3 without using jQuery

I have a simple collapse element in my Vue 3 template:
<template>
<button ref="myCollapse" class="btn btn-primary" type="button" data-bs-toggle="collapse" data-bs-target="#myCollapse" aria-expanded="false" aria-controls="myCollapse">
Toggle to collapse
</button>
<div class="collapse" id="myCollapse">
collapse content
</div>
</template>
I would like to be able to programatically open and close it. Manually adding/removing the show class does not preserve collapse animations.
Ideally the code would work like this:
<script>
export default {
name: "myCollapse",
methods: {
toggleCollapse() {
this.$refs.myCollapse.toggle()
}
}
}
</script>
Is there a way to achieve this, preferably without using jQuery? Is it correct to assume such way would work for other bootstrap components as well?

vue js navigate to url with question mark

my Vue js project login template click button it redirects to like this
http://localhost:8080/#/login to http://localhost:8080/?#/login
both Url show interface.
1st Url not set the local storage variable 'token'.
2nd Url is set the local storage variable 'token'.
how to solve it?
Login.vue
<template>
<div class="row col-sm-12">
<form>
<div class="form-group">
<label>Email address:</label>
<input type="email" class="form-control" v-model="email">
</div>
<div class="form-group">
<label>Password:</label>
<input type="password" class="form-control" v-model="password">
</div>
<div class="checkbox">
<label><input type="checkbox"> Remember me</label>
</div>
<button #click="login" type="submit" class="btn btn-success">Submit</button>
</form>
</div>
</template>
<script>
export default{
data(){
return{
email:'',
password:''
}
},
methods: {
login(){
var data = {
email:this.email,
password:this.password
}
this.$http.post("api/auth/login",data)
.then(response => {
this.$auth.setToken(response.body.token)
// console.log(response)
})
}
}
}
</script>
The form is getting submitted as the button you have provided in the form has type="submit" which is the default behaviour of a button present inside form even if you do not add the attribute type="button"
So replace the type submit to button o prevent form submission like this:
<button #click="login" type="button" class="btn btn-success">Submit</button>
I just faced the same issue, and the provided solution did not worked for me (Vue 2.5.17).
I had to add a modifier to the #click event to prevent the default behavior:
<button class="btn btn-primary" #click.prevent="login">Login</button>
Changing the button type to button, you disable default form behaviour, like pressing enter and release submit event.
Just add a modifier to the #submit or #reset event to prevent default behaviour:
<b-form #submit.prevent="onSubmit" #reset.prevent="onReset">
In order to keep the default behaviour of submitting the form using the "Enter" key on the keyboard as well, another solution is:
to keep the type = 'submit' on the button
handle the event parameter on the callback and process it with event.preventDefault(); like that:
login(event){
event.preventDefault()
var data = {
email:this.email,
password:this.password
}
...
}
Event.preventDefault() will prevent the default behaviour which is here to submit the form on the current url with the issue we are dealing with here.
See https://developer.mozilla.org/en-US/docs/Web/API/Event/preventDefault

In Vue - how can I trigger a broadcast to pick up event in a different control?

I have a component for steps, and I need to trigger an event in my steps component when I click on the next button.
This event should be picked up by a different component, that is representing the content of the page in the current step.
This is what I have tried:
Steps component template:
<template>
<div class="steps">
<div class="steps-content">
<section class="steps-panel" v-for="(stepPage, index) in steps">
<header class="posA wrap pTs">{{$t(title)}}</header>
<component :is="stepPage">
<!-- Summary component is injected here -->
</component>
</section>
</div>
<div role="navigation">
<ol class="fixed nav nav--block steps-nav w100">
<li class="steps-label txtCap" v-for="(stepPage, index) in steps">
{{$t(stepPage.name)}}
</li>
</ol>
<button class="steps-button" type="button">
<i class="pf pf-arrow-left"></i>
<span class="steps-button-label">{{$tc('previous')}}</span>
</button>
<button class="steps-button" type="button" v-on:click="next">
<span class="steps-button-label">{{$tc('next')}}</span>
<i class="pf pf-arrow-right"></i>
</button>
</div>
</div>
</template>
Steps component method:
methods: {
next(event) {
console.log('emit stepnext')
this.$emit('stepnext')
}
}
I call this with v-on:click="next" in the steps template (on the 'next' button)
From the console.log, I see that the click event is executed, and the $emit call does not trigger any error, so it seems to work fine at this point.
Summary component
The summary component is one of the components in `steps', and is loaded by this entry in the Steps template:
<component :is="stepPage"></component>
In the Summary component that knows what to do when this is clicked, I try to pick up on this event by having this in the template:
<div class="wrap" v-on:stepnext="stepfinish">
... content ...
</div>
... and a method in the summary component named stepfinish that does the action, but it seems like the emitted event never reaches my summary component.
How can I solve this?
A simple solution when using $root:
// trigger
this.$root.$emit('my-event');
// listen
this.$root.$on('my-event');
I think you are looking for the event bus
Here is some snippet from the official docs:
var bus = new Vue()
// in component A's method
bus.$emit('id-selected', 1)
// in component B's created hook
bus.$on('id-selected', function (id) {
// ...
})
link: https://v2.vuejs.org/v2/guide/components.html#Non-Parent-Child-Communication
Here is a blog on the same: https://alligator.io/vuejs/global-event-bus/
If you totally want to decouple your components, or you want to communicate across Vue "apps" and/or different frameworks (React, ...), then you can also use the DOM Native events:
document.dispatchEvent(
new CustomEvent("myapp:someClick", {
detail: {
id: 1,
someMoreCustomPayload: "bar",
},
})
)
And on the receiver's side:
document.addEventListener("myapp:someClick", (ev) => {
const { id, someMoreCustomPayload } = ev.detail
...
})
IE11 can also handle CustomEvents but apparently has no support for detail, but can be polyfilled.

Can't remove item from dynamically generated list

I'm having trouble with a function that I've created using scotch.io's VueJS guide. It's supposed to remove a function from the list on click, (triggering a view update) but I keep getting this console error:
[Vue warn]: Property or method "$index" is not defined on the instance but referenced during render. Make sure to declare reactive data properties in the data option.
(found in root instance)
The guide doesn't say to declare anything in the data option, what am I missing?
Here's the HTML:
<a href="#" class="list-group-item" v-for="event in events">
<h4 class="list-group-item-heading">
<i class="glyphicon glyphicon-bullhorn"></i>
{{event.name}}
</h4>
<h5>
<i class="glyphicon glyphicon-calendar" v-if="event.date"></i>
{{event.date}}
</h5>
<p class="list-group-item-next" v-if="event.description">{{event.description}}</p>
<button class="btn btn-xs btn-danger" v-on:click="deleteEvent($index)">Delete Event</button>
</a>
And the relevant JS:
new Vue({
...
methods: {
...
deleteEvent: function(index) {
if (confirm("Are you sure you want to delete this event?")) {
this.events.$remove(index);
}
}
}
});
There's already been a couple of cases where I've had to swap out deprecated directives that the guide uses, (v-repeat, v-on="click", etc) is the problem something similar?
The guide you are following is slightly outdated.
In Vue 2.0, using the index requires a little change in the syntax:
<a href="#" class="list-group-item" v-for="(event, index) in events">
<!-- You have to ask for it: ^^^^^^^^^^^^^^ -->
<button class="btn btn-xs btn-danger" v-on:click="deleteEvent(index)">
<!-- Then use it the way you named it: ^^^^^ -->
Delete Event
</button>
</a>

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

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?