In VueJS, how can I send an event to a custom directive - vue.js

I am using custom directive in Vuejs to render a pie chart (using chart.js), and I would need to notify the chartjs object to add a new segment or to remove a segment depending on the user's action.
While I can wrap the custom directive in a component so that it can receive events, how can the component communicate with the custom directive?

Related

Does OutletService support dynamically adding component in button handler

i used this.outletService.add('BottomHeaderSlot', factory, OutletPosition.BEFORE); during the search button click handler to add a custom component in the BottomHeaderSlot. I intended to add searchOverlay under the header to add customized search behavior.
But my custom component is not shown under the header after calling outletService.add. I refered to this https://sap.github.io/cloud-commerce-spartacus-storefront-docs/outlets/ . Does outletService support dynamic adding component during runtime?
Following is my button handler
open(): void {
const factory = this.componentFactoryResolver.resolveComponentFactory<SearchOverlayComponent>(SearchOverlayComponent);
this.outletService.add('BottomHeaderSlot', <any>factory, OutletPosition.BEFORE);
this.cd.markForCheck();
That's a good question. At the moment it is a not a feature supported from our outlets.
A solution you could do is inject the component in a more static manner (either CMS or outlet when the app initializes like seen here https://github.com/SAP/cloud-commerce-spartacus-storefront/blob/develop/projects/storefrontlib/src/cms-components/asm/services/asm-enabler.service.ts)?
Your component could then be wrapped with an <ng-container *ngIf="open$ | async></ng-container> where open$ is an observable for the state of the search box. That way the component only appears in the dom when the searchbox is open.
The idea of dynamically adding a components through outlets is a good one we will keep in mind. I will open an issue on Github as an improvement.

VueJS 2 - Default click event on component

Is it possible in VueJS to have a default click event on a custom component?
E.g. we have built a component called editable. Now on click, we always want it to fire the same function, no matter where we call that component.
<editable #click="doSomething" ...></editable>
Can I define that somewhere in the JS side?
In case of custom component, you need to bind to native event:
<editable #click.native="doSomething" ...></editable>
For documentation, refer to Vue.js docs here.

How to add a callback to a Vue root that triggers when child components update

I have a Semantic UI sidebar that uses the Semantic UI visibility module to highlight items in the sidebar menu as they're scrolled past in the page. I need to refresh this visibility config every time the page length changes. This happens a lot when my Vue page initially loads and then occasionally as the user adds bits to the page.
I'd like to just be able to add an updated callback on the root Vue element and have it trigger every time any descendant component updates but this doesn't seem to be a thing. Is there a way to do this tidily? I'd like not to have to litter a bunch of components with this updated callback.
you can use vue event bus to trigger events from different components.
First, initialize Vue.prototype.$bus = new Vue(); in your main.js file.
then use it to send events:
this.$bus.$emit('throw', 'Hi')
then let your main component listen:
this.$bus.$on('throw', ($event) => {
console.log($event) //shows 'Hi'
})

Can I add a custom directive or custom HTML code to a marker's pop-up message?

Can I add a custom directive or custom HTML code to a marker's pop-up message using ngx-leaflet?
For adding non-Angular HTML to a marker's pop-up, you should be able to use setContent, which is a vanilla Leaflet method.
https://leafletjs.com/reference-1.3.0.html#popup-setcontent

Initialize dynamic Component in Code using Vue.js

I am currently developing a web application that is used to display elements for events on a map provided by HERE Maps. I am using Vue.
I have some components, but the relevant component is the component HereMaps.vue which initializes the map using the HERE Maps Api.
The HERE Maps Api provides the possibility to place so called InfoBubbles on the map showing additional information. These InfoBubbles can be provided some HTML-code in order to customize their appearance.
Please refer to the documentation for additional information
Following the documentation the code looks something like this:
let bubble = new H.ui.InfoBubble(marker.getPosition(), {
content: "<div class='someClass'>Some Content</div>"
});
this.ui.addBubble(bubble)
This is happening after mount in the "mounted" method from Vue in the "HereMaps" component.
The Bubbles are added in a "closed" (hidden) form and dynamically "opened" to reveal their content when the corresponding marker icon on the map is clicked. Therefore the HTML-code is present on the DOM after the component is mounted and is not removed at a later stage.
Now instead of supplying custom code within each bubble added to the UI i want to just add a component like this:
let bubble = new H.ui.InfoBubble(marker.getPosition(), {
content: "<myDynamicComponent></myDynamicComponent>"
});
this.ui.addBubble(bubble)
It does not matter to me wether the component is initialized using props or if it is conditionally rendered depending on the state of a global variable. I just want to be able to use the "myDynamicComponent" in order to customize the appearance in a different file. Otherwise the design process gets very messy.
As far as i know this is not possible or at least i was not able to get it work. This is probably due to the fact that the "myDynamicComponent" is not used within the "template" of the "HereMaps" component und thus Vue does not know that it needs to render something here after the directive is added to the DOM in the "mounted" method.
This is what the InfoBubble looks using normal HTML as an argument:
This is what the InfoBubble looks using the component as an argument:
It appears to just be empty. No content of the "myDynamicComponent" is shown.
Does anyone have any idea how i could solve this problem.
Thank You.
Answer is a bit complicated and I bet you wouldn't like it:)
content param can accept String or Node value. So you can make new Vue with rendered your component and pass root element as content param.
BTW, Vue does not work as you think, <myDynamicComponent></myDynamicComponent> bindings, etc exists in HTML only in compile time. After that all custom elements(components) are compiled to render functions. So you can't use your components in that way.
Give us fiddle with your problem, so we can provide working example:)