How to emit a custom event from meta-data in Vue.js - javascript

I am trying to emit a custom event from a very rare situation.
I have a tab component where every slot inside has a name with 'row' and 'col' and each one corrisponds to <td>content here</td>, i must check inside the component if the slot is empty.
I am trying to emit a custom event 'no-content' only when the slot is actually empty.
My example
<my-component :meta-data="!$slots['td-'+row+'-'+col] ? $emit('no-content', 'td-'+row+'-'+col) : ''"
<slot :name="'td-'+row+'-'+col">
</slot>
</my-component>
is it actually possible to achieve this result with Vue.js? i tried myself and also searched for a case similar to mine but i found nothing.
PS: I actually spent a little more time trying to make it work but i had a problem with the component itself, so i started all over again but insted of using slots I work with an array of objects in input, now i reached the result I wanted to.
I'm gonna leave this here just in case someone else thinks about a solution with meta-data.

Related

Vuetify - Selected v-radio does not set value on v-model

I am trying to make a v-radio update a v-model value automatically but cannot get it working.
I have already achieved this with a check box like this:
<v-checkbox
v-model="arr1[index].isDone"
:disabled="checkRecordStatus(index)"
></v-checkbox>
With this code the isDone value for the specific array element is automatically assigned a value of true when the box is checked. That is, I don't need to call a function to set the value on the array element.
I am trying to achieve the same thing with a v-radio. Here is what I have:
<v-radio
v-model="arr1[index].isDone"
#change="radioSelect(index,'true')"
></v-radio>
I can get the value from the radioSelect function and set it on the model from there, but I am wondering if there is a way to do it without creating and calling a function, as with the checkbox example. I assumed that a selected v-radio would just set a true value on whatever was on v-model, but I seem to be missing something. I've had a look at the documentation and can't see anything that handles it.
Thanks for any help in advance!
From the base Vue docs, it looks like the way to override the default behaviour of a radio passing a string value is to also use v-bind:value, so you could do something like this I think (tested with a vanilla Vue2 component)
I am less familiar with Vuetify but if the component can accept v-bind the below should work:
<v-radio
v-model="arr1[index].isDone"
v-bind:value="true"
></v-radio>
https://v2.vuejs.org/v2/guide/forms.html#Radio-1

Angular Directive not working with *ngIf. Calling directive from component

I have two DIVs - one, that is always visible, and another one, that gets displayed after I click a button (it is toggable):
<div>
<div>
<small>ADDRESS</small>
<p [appQueryHighlight]="query">{{ address}}</p>
</div>
</div>
<div *ngIf="showDetails">
<div>
<small>NAME</small>
<p [appQueryHighlight]="query">{{ name}}</p>
</div>
</div>
My custom directive works well on the first DIV (it changes the color of letters inside the paragraph that match the query entered in an "input"), but does not work on the second DIV.
Here is an example of how "Test address" looks like when query is "addr":
Test addresswhere bold text is for example red-colored text.
But when I have name John, and query is "Joh", it should also be colored once shown with the button, but it is not.
As I understand, I need to re-run the directive after I click and toggle the second div. Also, probably I have to do this with delay, so it has time to be shown. How can I do this?
UPDATE
Problem with my directive is related to *ngFor - both DIV are located withing ngFor. I have to call directive ngOnChanges or ngOnInit only after the new list get propagated based on the query. I have no idea how to do this, and currently, directives get loaded before ngFor fully loads - this cause problems.
Here is my previous answer:
I finally managed to solve this problem, thanks to #iHazCode.
So firstly, this is probably a duplication of problem described here: Angular 4 call directive method from component
Because my directive hightlights the specific letters in paragraph based on input query, each time the query changes, the directive should fire, thus I am using ngOnChanges withing the directive.
This is not working with *ngIf, because when ngOnChanges fires, the second div and paragraph is not visible.
As a workaround, we can access the directive from out component using #ViewChildren:
#ViewChildren(QueryHighlightDirective) dirs;
And then call it's ngOnChanges method, once div is toggled. In my case, the problem was related with last occurence of the directive within the component:
toggleDetails() {
...
this.dirs.last.ngOnChanges();
}
That was exactly what I was looking for, I hope it will help someone.
In my case I also encountered another problem - the defined DIVs are within *ngFor, which is also propagated based on the query, so I have to make sure that the list will get propagated before calling ngOnChanges. I haven't find a solution for this yet.
ngIf does not show/hide elements. ngIf determines if the element exists on the DOM. You can verify this by looking at the source of your rendered page. Change the code to use ngHide/Show instead.

Vue.js: Communicate with components that are down the DOM

I'm just trying out Vue.js and I'm struggling with the key concept of passing information up and down the DOM from one component to the other.
Consider this example in which a container-toggle button should toggle all components within the container, or say, set them all to "true" or "false".
<div id="app">
<p>
<strong>Welcome!</strong>
Click the "true/false" buttons to toggle them.
Click the "Toggle all" button to toggle them all!
</p>
<app-toggle-container>
<app-toggle></app-toggle>
<app-toggle></app-toggle>
</app-toggle-container>
<app-toggle-container>
<app-toggle></app-toggle>
<app-toggle></app-toggle>
<app-toggle></app-toggle>
</app-toggle-container>
</div>
In this code pen, I've defined app-toggle and app-toggle-container as components: https://codepen.io/fiedl/pen/mmqLMN?editors=1010
But I can't find a good way to pass the information down from the container to the separate toggles.
Also, in a second step, when trying the other way round, for example, to have the "Toggle all" button just show "true" if all toggles are true, or to show "false" when all toggles are false, I can't find a way to pass the information of the current state of the toggles up to the container.
This doesn't seem like an uncommon problem. What is the proper way to do this in Vue.js? Or am I thinking about this it in the wrong way?
Quickly, I've found $broadcast and $dispatch. But as they are dropped in Vue.js 2, I'm most probably thinking about it in the wrong way :)
I forked your pen http://codepen.io/nicooga/pen/wdPXvJ.
Turns out theres a $children property for Vue components that contains your children components [controllers]. You can iterate over them and do stuff with them.
this.$children.forEach(c => c.toggle());
See
https://v2.vuejs.org/v2/api/#vm-children
VueJs Calling method in Child components.

PrimeNg Checkbox execute function

I've been trying to get a function to happen whenever I press a checkbox in a datatable. Basically what I have is a datatable with default values in it (1 to 10 for example). Then I give an array of items to my component which are present in an object of mine (2 & 5 for example). now when the grid is constructed It'll all the default elements in the dataTable but Only the data that is in our object will have a checked checkbox next to them. Now what I want to do is to have my addOrRemove function executed wich depending on the state of the checkbox will add or remove a default data object from the array ([2,5] in this case). So 2 or 5 can be unchecked and thus removed from the array and 1,3,4,6,7,8,9,10 can be checked and added to the array.
I don't realy have a problem writing the code for this but I'm struggling to have my function being executed whenever I press the checkbox.
this is how I have my checkbox defined in my html file:
<p-column header="Included" [style]="{'width':'80px', 'text-align':'center'}">
<template let-object="rowData" pTemplate="body">
<p-checkbox binary="true" [(ngModel)]="object.included" (change)="addOrRemoveRow($event,object.data)"></p-checkbox>
</template>
</p-column>
using this I'm not getting any functions triggered.
In the PrimeNg documentation there is stated that p-checkbox has an event onChange. but whenever I use that I'm getting the error.
EXCEPTION: Error in http://localhost:3000/app/shared/grid/checkable-grid/checkable-grid.component.html:9:12 caused by:
self.parentView.context.addOrRemoveRow is not a function
That is whenever I change the (change) to (onChange).
I've read that it has something to do with my checkbox being inside of a template and therefore there is no direct access to my component and its functions. Any help on this would be much appreciated.
The answer to this question is:
Make sure you take enough breaks and read your code carefully. In my component I have a function called addOrRemove(), in my html I had addOrRemoveRow().

How to programmatically add components or views inside other components/views in ember js

I have a component say {{component-1}} which gets called many times and creates a custom-texbox container and label as many times as it gets called.
Now whenever a user writes something in it a suggestion box should appear below it. Since the suggestion box can be reused everywhere i dont want to have a separate suggestion box for each {{component-1}}, rather i want to have another component called {{suggestion-box}} that gets inserted inside component-1 i.e. the textbox container.
I dont want {{suggestion-box}} to be inside dom at all since it is needed only when somebody types in it. I want to add/insert it into {{component-1}} when someone types. Instead of a component i even tried to use a view
Here are the different things i have tried and failed
Note:
suggestionBox is the component
textbox-container is an element inside {{component-1}}
Inside {{component-1}}this.$().find(".textbox-container").append(this.suggestionBox );where this.suggestionBox = suggestionBoxComponent.create(); I have event tried suggestionBoxView.create();It gives me the error that i one view cant be inserted into another and i need to use containerView
var tmp = Ember.Handlebars.compile('<div class=".suggestionBox"></div>');this.$().find('.textbox-container').append(tmp());I get the error called
Uncaught TypeError: Cannot read property 'push' of undefined
I even tried to use view instead of component i.e. make suggestionBox a view but then again i cannot insert one view inside another
I have tried a lot more things.
Few points:
I dont want alternate solutions of how textbox and suggestion box could be created
How to pass information from a component or a a template to a view? Say i do {{view "suggestion-box"}} inside component-1 template, how do i pass values to it? Say for components we pass in the context like this {{component1 sampleVar1=val1 sampleVar2=val2}}
i Want to know how to programmatically add a component or a view and if it is a view how to pass the data to it?
I dont want to use container-view since it will cause more complexities, however if your solution allows me to pass value from {{component-1}} to container-view and inturn pass it to corresponding childView1 and childView2 then that solution is acceptable
Just an update:
I even tried to use a view container inside the {{component-1}}
I also tried to use view block inside {{component-1}} i.e.
{{#view "view-name"}}
----earlier component elements here-----
{{/view}}
In both the above points "view-name" is a ContainerView which is getting inserted properly but the component element are not getting inserted
This can be achieved with a ContainerView and the viewName attribute. The component or view can access the ContainerView or any other view that is part of a template through its assigned viewName.
Example,
hbs
{{view Ember.ContainerView viewName="my-menu-container"}}
js - then from the component or view
this.get("my-menu-container").pushObject(suggestionBoxViewOrComponent);
http://emberjs.jsbin.com/yoyujeqi/1/edit
p.s. the context of the example is not relevant to the suggestion box, sorry about that, as it has been extracted from another answer related to adding a menu view dynamically.

Categories