I have a user-configurable layout where I believe I would need to change nesting of elements per configuration. I don't want multiple templates, as this would be a chore to maintain, but I would like to know if there is some way in Angular 2 to define a parent element whose child elements will display weather or not the parent element is displayed. So if I have:
<parent>
<child />
</parent>
I would like to use some sort of toggle to remove the parent element from the display list without losing it's child. So upon toggling off, child would become a child of parent's parent.
Is that even possible?
If parent is just an HTML tag, this can be accomplished indirectly using CSS classes that are applied conditionally.
For example, if parent is a <div>:
Template:
<span [class.myDivClass]="condition">
<child />
</span>
CSS:
.myDivClass {
display: block;
}
If parent is an Angular component, it may be easier just to add an input to it that disables its functionality instead of trying to un-nest it.
Alternately, it might be possible to create a directive that could have this type of effect.
Related
I have a custom component in angular that i re-use everywere in my app. This is a button component and i call it like this where i want to use it: <app-delete-btn></app-delete-btn>
I want to set the attribute tabindex="1" to my component but it does not work.
This attribute gives a TAB order to specific html elements.
Upon inspecting this strange behaviour, and as of my understanding, tabindex works but you have to specify it for the parent and ALL the child components
So i did this and it worked:
Upon declaring my custom component in my html <app-delete-btn tabindex="1"></app-delete-btn> i gave him the tabindex
and then i had to add it in the app-delete-btn.ts button inside the component <button tabindex="1">Delete</button>
The problem is that i may re-use that button therefore i can't add the tabindex from within the component itself otherwise is going to apply everywhere i use it.
Finally my question is:
Is there a way when calling <app-delete-btn></app-delete-btn> to assing a tabindex property to all of it's childrens (and by childrens i mean the button delcared in the html of the component)?
Add this to your button :
#HostBinding('attr.tab-index')
tabIndex = 1;
This should do the exact same thing as this
<app-delete-btn tabindex="1"></app-delete-btn>
But automatically
I'm learning Vue.js. Here I want to design a checkbox component like this:
<xxx-checkbox-group>
<xxx-checkbox></xx-checkbox>
<xxx-checkbox></xx-checkbox>
</xxx-checkbox-group>
Above are two kinds, the parent checkbox-group and the child checkbox. The checkbox-group use <slot> to get the children component and have some necessary data. I want the child can use some parent's data(just use not change). It's a bit troublesome and inefficient if I put a attribute in every child's tag.
<xxx-checkbox-group>
<xxx-checkbox shape="square"></xx-checkbox>
<xxx-checkbox shape="square"></xx-checkbox>
</xxx-checkbox-group>
Can I pass the value by other ways? So that I can controll all the children's state through the parent. I think it's possible but I can't find the way to achieve that.
<xxx-checkbox-group shape="square">
<xxx-checkbox></xx-checkbox>
<xxx-checkbox></xx-checkbox>
</xxx-checkbox-group>
For me it's not fully clear what's your intention, so can you create a small jsfiddle example?
but in general, within a child component you can access to it's parent vue instance via this.$parent to read & change properties.
I created a couple of reusable components with a slot within it. So I can manage the content, style, or whatever it is anytime I call it, in other components. I wonder, can I passing an event handler to
those components but inside the template tag?
ReusableComponent
<a :href="hrefProps"> // I want the handler goes here
<slot></slot> // it will render plain text, without html tags
</a>
Main Component
<reusable-component>
<template #click="sayHelloWorld">Hello World!</template> // didn't work
</reusable-component>
How can I make that to work? Should I wrap them into at least 1 tag, like
<template><a #click="sayHelloWorld"></a></template> // sure it will working
Template tags don’t create a DOM element, so pi can’t add a listener to them, or add a class or anything else.
They are just a semantic tool to wrap multiple children in a loop.
Add the listener to the real parent element i-e href tag
In Vue.js, I have a var app = new Vue({...}); and I have a component Vue.component('mycomponent', ... where I can use such component without any issue by directly adding <mycomponent></mycomponent> in html. What I wish to do is to dynamically add those component on demand maybe after a button click or when some other such event takes place. In raw JS, I'd use document.createElement... when event fires and then do el.appendChild.. to add it into html. How would I do the same with Vue.js ?
I'm not doing anything fancy with node js. This is on a single html page with <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> in the <head>.
To do this the "Vue way" usually involves the use of v-if, v-for or <component>, depending on what you want to do:
Use v-if to conditionally show a component/element based on a condition.
Use v-for to render a list of components/elements.
Use <component> to render a dynamic component/element.
So to achieve what you described in your question, you can declare a boolean data property visible like this:
data() {
return {
visible: false
}
}
and use it with v-if to control the visibility of a component in the template:
<mycomponent v-if="visible"></mycomponent>
This requires that <mycomponent> exist in the template upfront. If you don't know what kind of component you want to show, then you can either include each possibility in the template and display the one you want based on some condition:
<comp1 v-if="comp1Visible"></comp1>
<comp2 v-if="comp2Visible"></comp2>
<comp3 v-if="comp3Visible"></comp3>
or you can use <component> together with another data property (comp) which you can set to the name of the component you want to display:
<component v-if="visible" :is="comp"></component>
What you described (document.createElement followed by el.appendChild) does not exist in Vue. Vue has a strict rendering mechanism which you need to work with; it isn't possible to dynamically instantiate components and stick them into the DOM randomly. Technically you can do comp = new Vue() as an equivalent to document.createElement and then el.appendChild(comp.$el), but that probably isn't what you want to do because you would be creating an independent Vue instance that you would have to manage manually with no easy way of passing data around.
I like to think of Angular components as element directives. Given a component called hero I can use it in the parent template like this:
<hero myparam="something"></hero>
I'd like to use the hero element as a component-managed container, with the component being in charge of the whole element.
EXPECTED
Here's what I hope to get out of the binding from above:
<hero id="component123" class="alien" custom="foo">text</hero>
My custom component transforms the given element and uses it as it sees fit.
ACTUAL
However, it seems the component can only render its template inside the hero element. Best I can get is:
<hero myparam="something">
<div id="component123" class="alien" custom="foo">
text
</div>
</hero>
I feel this is bad because the hero element is not actually the hero, but merly a wrapper for the actual hero. This mixes up the semantics and creates unwanted extra elements.
Is it best practice in Angular to use components as pure wrappers and putting the actual components inside?
Here's an official sample to play around with:
https://plnkr.co/edit/NKjCDS8OEngYHNrBmC5O?p=preview
I like to think of Angular components as element directives.
A component could be thought of as a special kind of directive that updates a template. If you want to change attributes, use an actual directive (attribute directive)
My custom component transforms the given element and uses it as it
sees fit.
When you talk about transforming, you want directives, not components.