Detect when child component is rerendered - aurelia

I have a link element injected into translation string that I later consume via aurelia-i18n plugin. I need to listen for a click event on this link. As far as I researched it is not possible to add click.trigger="function() to an html element in translation string.
So I ended up just manually assigning a listener to the link DOM element in attached method of parent component. However when language updates, link updates as well and my listener is gone. Is there a way to know when component has been updated so I could reassign the listener there?
Or is a better solution to this issues?

Related

Vuetify dialog adds new dialog to dom each time it is opened and exon't remove the previous on close

We have a large scale application but in Vue 2, Composition API and Nuxt.
However we load a lot of content in dialogs. After using the application for several minutes you can see a build up of these dialogs in the DOM.
Is there a way for Vuetify to use the existing dialog one instead of creating a new instance.
Or remove the existing one on close?
I can't see anything in the docs or similar issues from other users.
Each v-dialog with a v-model will be added to the DOM first time it's active/opened, then the visibility is changed on subsequent toggles. It's more "expensive" to add and remove DOM elements (size depending on its nested content) than toggle an active class and add a simple overlay. Probably why it's not recommended to nest v-dialog within a v-for loop, the DOM will get too crowded. If the dialog content is interchangeable, you could have one dialog on the page where the content is toggled too.

How to render markup so there's less FLOUT with a Vue Component?

I need to render a list of items (server rendered), each item has a countdown timer. When I just have my view component in each dom element there's nothing there, then POP, the view component renders the countdown... Now I know this value on the server side as well, is there some way to render it immediately such that the vue component will takeover the rendering? (Does that make sense)
Like the html from the server renders 50:32 (minutes, seconds), but then the view component takes over, removes it and starts the countdown 50:31, 50:30... etc etc.
I've tried passing the server val in as a prop and just rendering it inside the node, still pops (I assume because the component is rendering...)
Is this even doable, or am I stuck with a loader?
Thank you for your relevant question, I propose an answer from what I understand.
you are trying to dynamically pass a property from the server to a view instance already created. This is not possible because Vue does not allow dynamically adding new root-level reactive properties to an already created instance. However, it’s possible to add reactive properties to a nested object using the
Vue.set(object, propertyName, value) method:
Vue.set(vm.someObject, 'b', 2)
go on the official documentation of Vue to know more
here : https://v2.vuejs.org/v2/guide/reactivity.html
hope that it puts you on the right track

Default-expand-all doesn't work for q-tree? Vue.Js

I have to code a web application and the most important element is the q-tree. I'm already able to load and show data (passing an array called list), but I want that all nodes are expanded.
The vue.js examples of the official documentation show that you're be able to do this with the 'default-expand-all' attribute but this isn't working for me.
It only shows me the root node with an arrow, where I have to expand the children nodes manually.
<q-tree
:nodes="list"
:selected.sync="selected"
#update:selected="onSelectionChangedNode"
node-key="NodeNr"
label-key="NodeTxt"
default-expand-all
></q-tree>
Taking a cue from the accepted answer, I realised that the dom has already been created with the tree component on first render.
In my use case, I want to update the Tree when data comes back from the server.
So, I had to force it to re-render with the expanded functionality using:
this.$nextTick(function () {
this.$refs.nodes.expandAll();
})
The nextTick function will update the dom in the next window of execution, by which time the nodes will get expanded by calling the expandAll function.
And NB: For those confused by the astericks on the ref attribute or how to add it to the component, here goes:
<q-tree :nodes="list"
:selected.sync="selected"
#update:selected="onSelectionChangedNode"
node-key="NodeNr"
label-key="NodeTxt"
ref="nodes"
>
Solved my problem as following:
I have added a ref attribute to the QTree DOM Element which makes it possible to access predefined methods of QTree API.
<q-tree
:nodes="list"
:selected.sync="selected"
#update:selected="onSelectionChangedNode"
node-key="NodeNr"
label-key="NodeTxt"
**ref="nodes"**
>
The function I have been using is expandAll().
updated() {
this.$refs.nodes.expandAll();
}
The most important thing for me was, I had to find out which lifecycle hook was the right one for me. The update() hook was the one I was looking for.
The reason:
Called after a data change causes the virtual DOM to be re-rendered and
patched.
The component’s DOM will have been updated when this hook is called, so you
can perform DOM-dependent operations here.
The default-expand-all is only applied on the first rendering of that Component.
So if your Component renders when the nodes aren't assigned they wont expand if assigned afterwards.
https://v1.quasar-framework.org/vue-components/tree
You have to work with scoped slots and an expanded attribute if you dont have the nodes on first rendering.

Firing an event from parent to child element in Polymer 2.0

Can somebody provide an example of sending an event from parent to child in Polymer 2.o custom element?
I tried with following:
<child-element>
this.addEventListener('dbinit', this._evdbInitStatus);
and
<parent-element>
this.dispatchEvent(new CustomEvent('dbinit', {detail: {kicked: true}}));
The call back does not get invoked.
This is not really related to Polymer itself, as you can see in the documentation on how events work, here, events capturing stops at the element that triggered the event and the event bubbling (as the name suggests, the events bubble up) starts from the element and goes up in the tree.
So, in other words, an event fired by a parent element won't be captured by a child element. You will need to use a data binding to pass data down.
To keep a consistent, predictable flow of data, in general, it's better anyway if data travels down via data binding and up via events.

How to communicate between components within a certain component?

Suppose I have a tree of component like this:
<widget>
<widget-header>
<panel-toggle></panel-toggle>
</widget-header>
<widget-body>
<panel></panel>
</widget-body>
</widget>
Now supposed I want the panel-toggle component to be able to toggle the visibility of the panel component. I could have it affect a prop passed down from widget through to each component, but that didn't seem like the best solution. I tried sending an event with this.$emit(eventName) but the event is only picked up by the immediate parent of the element emitting the event. In this case, that would be panel-toggle emitting the event and only widget-header being able to pick it up. I tried sending the event across the root element with this.$root.$emit(eventName) and picking it up with this.$root.$on(eventName), but then it is picked up by all widget components and that is no good. What I ended up doing is sending the event with this.$parent.$parent.$emit(eventName) and then picking it up from panel with this.$parent.$parent.$on(eventName). While that worked, it doesn't seem like the right way to go about this.
What would be the correct way to achieve this communication between components within the component widget only with Vue? Is the answer somehow related to the ref feature?
Since you're concerned (and with good reason) about the globalness of a global event bus, the solution is a localized event bus. Create a data item in the parent:
panelBus: new Vue()
and pass it to each of the children as a prop. Now they have a private communcation channel for just the two of them.