Nested components in Vue.js - javascript

I struggle in creating nested components where each layer includes templates:
<wizard>
<step name="first">Do this step first!</step>
<step name="second">This should follow</step>
</wizard>
(full example: http://jsfiddle.net/maxhq/9o4qxd7t/)
I only get templates to work either for parent or for child components, never for both.
if parent has no template and is used with <... inline-template>, child components (and their templates) are evaluated (like in http://jsfiddle.net/hajkrupo/3/)
if parent includes a template (even with special tag <content>), then the child components do not get inserted/evaluated
Can this be solved in vue.js?

If you're using the latest vue.js version (1.0.26 at the time of writing) your problem is using <content></content> as the syntax was changed to <slot></slot>
JSFiddle

No. inline-template means you define template inline there there:
When this param is present, the component will use its inner content as its template rather than transclusion content. This allows more flexible template-authoring.
You can do it this way: http://jsfiddle.net/8k335nrf/

Related

How to pass rendered Vue component as parameter?

I use Vue, vue-fontawesome and v-tooltip. What I simply try to do is this:
<button v-tooltip="<fa icon='sign-out-alt'/>">Upgrade</button>
But that doesn't work, component passed as strings are not rendered. How to get it done easy way?
In this specific use case, there's an example for that in v-tooltip readme
If you need to display components inside the tooltip (or
popover/dropdown, technically it's the same 😄), use the v-popover
component
Here's an example of using a child component as a popover. Instead of my child component, you would use your <fa icon='sign-out-alt'/> icon.

Angular - dynamically inject content to <ng-content> component

I have composition of components
ComponentA
<div class="CA"><ng-content></ng-content></div>
ComponentB
<div class="CB"><ng-content></ng-content></div>
And in parent I want to use them like this:
<component-a>
<component-b>
// I want something here
<div>some-content injected from parent<div/>
</component-b>
</component-a>
So, my components are designed to be composable and parent requires access to all components from it's scope - without shadowing api.
What I want to do is also affect children of component-b from component-a. I want to access I want something here from ComponentA.component.ts and inject something there.
Real life example:
<app-input-with-buttons (onButtonClick)="someCallback()">
<app-input [validationMessage]="someValidation$ | async">
<input ngModel />
</app-input>
</app-input-with-buttons>
I need InputWithButtonsComponent to inject HTML to InputComponent children.
I know it "too React way", but this approach allows me to limit components to single responsibility, allowing form component to control each step of form control.
Is it possible to access many nesting levels of ng-content in Angular? Also, are there better architecture patterns for solutions like this?

Angular 5: creating a parent component with an external template and overriding the inner part

I'm trying to create some sort of parent component that gives me some general appearance and logic for all my components, but in which I can write some specific logic and templating inside.
Look at these images:
Both of these components have common traits: an upper part with a title and a "hide/show" button, and then, a "body" that differs between both of them. They also share that edit button and so, but my idea is to make that "body" part completely dynamic: that's the part of the component that I want to override with my implementation components.
In other words: I want to make an abstract class with Typescript that holds the template: the rectangle, the header and body, the title (which I want to override from the subclass)... and then, the "body" will be filled with the template provided by the subclass.
How can this be achieved in Angular? This far I've only seen ways of overriding completely the parent components templates, not to complement one with the other. I guess there must be a way to insert HTML code with Angular directives inside a component...
Thing is, which is it?
Thank you!
Let's assume you named your component CardComponent and your selector is app-card.
For the title
You can simply use the #Input() component decorator to get the title string and use it in your generic CardComponent, see the angular documentation: https://angular.io/guide/component-interaction
For the body:
You can create your component containing the header and Edit button and then use the <ng-content> tag to get what's inside the component selector, for example:
<h2>{{title}}</h2>
<ng-content></ng-content>
<button>Edit</button>
And so you can use your card component like this:
<app-card [title]="Channel select">
<!-- Insert your body html -->
</app-card>
PS: to learn more about ng-content, see this: https://medium.com/claritydesignsystem/ng-content-the-hidden-docs-96a29d70d11b

Multibrand strategy in angular 2/4

I have an use case which requires me to style an angular component several different ways. I am building seperate components (buttons, lists etc..) for other developers to use for their respective brand. For exampe, the same angular component could be used in 4 different sites (thus the component is exported as a module), but all sites require different css for this component.
What does angular 2/4 cli offer to accomadate this ?
You have several options :
1. Stay very basic with your template
Sometimes, you can do the job with only one DOM node. Build a VERY basic template which can be placed everywhere without affecting the DOM or the styling, and let your collegues create the rest of the template. Thus, the component will not depend on your template, your class names or any styles you would have created otherwise.
Of course, this is kind of an extreme solution :) !
2. Build your component as a wrapper with internal logic
Suppose you need to create a button. Instead of creating a template with a button element, you could also create a div element which contains all the logic you need (a (click) event handler for exemple). This element is going to wrap a button provided by your collegues through transclusion. See below a possible custom-button component template :
<div (click)="handleClickEvent($event)">
<ng-content></ng-content>
</div>
In the parent component you may imagine to have this :
<custom-button>
<button class="btn btn-primary">
<i class="fa fa-chevron-right"></i>
</button>
</custom-button>
3. Use a classic html/css method
Give a template to your component and add class names to the DOM nodes in a way your collegues will be able to style them with a basic CSS.
It will be easy for you to prepare the component, but your collegues may be blocked by the names you choosed or the way the nodes are nested.
4. Give an entry point to provide styles used by the component template
For this, you will need an #Input() variable.
#Input() customStyles: any;
The variable will be provided to a HTML node through [ngStyles].
<button [ngStyle]="customStyles">Send</div>
The customStyles will necessarily be an object of a specific format (see official documentation here).
In the parent template, you could provide the styles like this :
<custom-button [customStyles]="{'max-width.px': widthExp}"></custom-button>
The problem here is that you have to provide as much variables (entry points) as you need to style all DOM nodes of your template...
5. Give an entry point to provide a class
Like before, a variable holds a value provided by your collegues in the parent template. Here, you expect a string to be provided, corresponding to a class name.
#Input() customClass : string;
In your template, you are going to add this custom class to the outer div
<div class="someClass {{ customClass }}> <!-- Outer div -->
<!-- Some DOM elements -->
</div>
Then, your collegues will be able to provide a class and to style all children elements in a CSS file according to the structure you create.
.bigButton {
height: 500px;
width: 1000px;
}
.bigButton > div {
padding: 100px;
}
.bigButton:hover > div {
// ...
}
In the parent template :
<custom-button [customClass]="'bigButton'"></custom-button>

AngularJs (1.5+) dynamic binding

We are developing our own library of AngularJs (1.6.x) components/directives and we would like to have all HTML attributes that are specified on our components automatically and dynamically passed on to the underlying templates, without having to specify every single attribute as a binding.
For example, if I have a component like <my-component> with a template like <div class="my-component"></div> and I write in my HTML:
<my-component ng-required="ctrl.isRequired" ng-change="ctrl.onChange()" ng-attr-disabled="ctrl.isReadOnly"></my-component>
I want my template to render:
<div class="my-component" ng-required="ctrl.isRequired" ng-change="ctrl.onChange()" ng-attr-disabled="ctrl.isReadOnly"></div>
As I said above, we cannot know in advance all attributes, so they can't all be defined in the component bindings. The problem gets more complicated in Angular 1.5+, because replace has been deprecated, so the above template would render something like this:
<my-component ng-required="ctrl.isRequired" ng-change="ctrl.onChange()" ng-attr-disabled="ctrl.isReadOnly">
<div class="my-component" ng-required="ctrl.isRequired" ng-change="ctrl.onChange()" ng-attr-disabled="ctrl.isReadOnly"></div>
</my-component>
And also, when we have nested, deep hierarchies of components, we want the values to be passed down from the parent controllers to the (grand)children, i.e. the ctrl.onChange() method will be defined in the scope of the page controller where <my-component> is defined, but as each component in the hierarchy gets its own scope, as you go deeper, we want the method to still be callable.
I am relatively new to Angular, I hope the above make sense.

Categories