Rupert  Beatty

Rupert Beatty

1671660840

How to Reusable Component Pieces with ngTemplate Outlet

tldr;

ng-template, ng-container, and ngTemplateOutlet provide the ability to reuse content inside an Angular component. Understanding what’s going on and how to use these methods allows a developer to build what they want without needing to duplicate parts of the template.

Explanation of the Problem

Have you ever needed to use *ngIf in your template, and if the expression evaluates to false use a backup template? On top of that, maybe both situations (if the expression is true or false) require the same layout inside of the element that has the *ngIf directive on it.

I recently had came across this situation. We had some data that was being output in a list either had a link that stayed internal to the app or opened a link in a new tab external to the application. The content inside the links, however, always had the same layout. I didn’t want to duplicate the inner content, and luckily Angular provides the ability to accomplish this. The method includes using ng-template, ng-container, and ngTemplateOutlet.

Before getting to the end solution, let’s look at an example of the data and how it’s output without using ng-template.

export class ListComponent {
  links = [
    { internal: true, display: "Home", url: "/" },
    { internal: false, display: "External", url: "https://test.com" },
  ];
}
<ul>
  <li *ngFor="let link of links">
    <a *ngIf="link.internal" [routerLink]="link.url">
      <img src="/assets/icon.svg" alt="">
      <span>{{ link.display }}</span>
    </a>
    <a *ngIf="!link.internal" [attr.href]="link.url">
      <img src="/assets/icon.svg" alt="">
      <span>{{ link.display }}</span>
    </a>
  </li>
</ul>

In this method, we have two *ngIf directives on two separate a tags, and the inner content of the link is the same in both cases. If that inner content changes, we have to make the change to both places or else there are inconsistencies in the layout. This is not ideal; we are repeating ourselves and there are multiple locations where we can introduce bugs.

Solution

Angular provides a much more elegant solution to our problem. Our TypeScript code from above will remain the same, but we can have a lot less duplication in the HTML by using a couple special Angular tags. First I’ll show the HTML, and then we’ll discuss the different pieces.

<ul>
  <li *ngFor="let link of links">
    <a *ngIf="link.internal; else externalLink" [routerLink]="link.url">
      <ng-container
        [ngTemplateOutlet]="linkLayout"
        [ngTemplateOutletContext]="{ link: link }"
      ></ng-container>
    </a>
    <ng-template #externalLink>
      <a [attr.href]="link.url">
        <ng-container
          [ngTemplateOutlet]="linkLayout"
          [ngTemplateOutletContext]="{ link: link }"
        ></ng-container>
      </a>
    </ng-template>
  </li>
</ul>

<ng-template #linkLayout let-link="link">
  <img src="/assets/icon.svg" alt="" />
  <span>{{ link.display }}</span>
</ng-template>

There’s a lot going on here, so let’s break it down. We’ll start with the *ngIf on the a tag.

<a *ngIf="link.internal; else externalLink" [routerLink]="link.url">
  <ng-container
    [ngTemplateOutlet]="linkLayout"
    [ngTemplateOutletContext]="{ link: link }"
  ></ng-container>
</a>
<ng-template #externalLink>
  <a [attr.href]="link.url">
    <ng-container
      [ngTemplateOutlet]="linkLayout"
      [ngTemplateOutletContext]="{ link: link }"
    ></ng-container>
  </a>
</ng-template>

The *ngIf directive has an expression listed: if link.internal evaluates to true, then show this a tag. If it’s false, output the ng-template tag that’s referenced by the externalLink local template variable. This is how we can either navigate to a new route that’s part of the Angular app or external to the app. This is a method that can be used in any situation where your *ngIf needs an else clause.

Next up, let’s look at what’s going on with the ng-container inside both of the a tags in the example.

<ng-container
  [ngTemplateOutlet]="linkLayout"
  [ngTemplateOutletContext]="{ link: link }"
></ng-container>

You can read more about the ng-container element in the Angular docs, but at a high level it’s a special element that can hold structural directives without adding new elements to the DOM. It can also be used in situations like this, with the ngTemplateOutlet structural directive. The ngTemplateOutlet directive determines what ng-template will be output on the page inside the ng-container. The context for the template, or needed variables, can be declared with the ngTemplateOutletContext directive. In the above case, we are saying that the #linkLayout content should be output on the page, and that there should be a variable called link that will be used inside the ng-template. The contents of the ng-template tag can be placed anywhere in the HTML file, though I’ve placed them at the bottom in this example.

<ng-template #linkLayout let-link="link">
  <img src="/assets/icon.svg" alt="" />
  <span>{{ link.display }}</span>
</ng-template>

This template will be output on the screen anywhere it’s referenced. In this case, inside both a tags. If we want to change the layout inside the a tags, we need only change this one spot in the HTML. Everything will be kept in sync, and we have fewer possibilities of inconsistencies in the component.

There is one alternate way of declaring the ngTemplateOutlet. The result will be the same as the method shown above.

<ng-container
  *ngTemplateOutlet="linkLayout; context: { link: link }"
></ng-container>

Conclusion

The above method limits the duplication to a certain degree, especially for the content inside the a tag. The example here is a fairly simple layout. This method becomes more useful when the internal layout becomes more complicated. That inner layout is defined once and reused in multiple locations. You could create a new component if you wanted, but that can introduce complexity sometimes as well.

Knowing how to use ng-template, ng-container, and ngTemplateOutlet can allow you to effectively output the content of a component with minimal duplication.

Original article source at: https://www.prestonlamb.com/

#angular #ng #template 

What is GEEK

Buddha Community

How to Reusable Component Pieces with ngTemplate Outlet

Learn Angular : Creating Reusable Angular Components | @Input | @Output

#angulartutorials #beginners #components #reusable
In this Angular tutorial, you’ll learn how to create re usable Angular components using @Input and @Output directives.

You can read the Angular tutorial at CodeHandbook blog https://codehandbook.org/creating-reusable-angular-components/

Source code from this tutorial is available at GitHub https://github.com/jay3dec/reusable-components

#angulartutorials #beginners #components #reusable

Rupert  Beatty

Rupert Beatty

1671660840

How to Reusable Component Pieces with ngTemplate Outlet

tldr;

ng-template, ng-container, and ngTemplateOutlet provide the ability to reuse content inside an Angular component. Understanding what’s going on and how to use these methods allows a developer to build what they want without needing to duplicate parts of the template.

Explanation of the Problem

Have you ever needed to use *ngIf in your template, and if the expression evaluates to false use a backup template? On top of that, maybe both situations (if the expression is true or false) require the same layout inside of the element that has the *ngIf directive on it.

I recently had came across this situation. We had some data that was being output in a list either had a link that stayed internal to the app or opened a link in a new tab external to the application. The content inside the links, however, always had the same layout. I didn’t want to duplicate the inner content, and luckily Angular provides the ability to accomplish this. The method includes using ng-template, ng-container, and ngTemplateOutlet.

Before getting to the end solution, let’s look at an example of the data and how it’s output without using ng-template.

export class ListComponent {
  links = [
    { internal: true, display: "Home", url: "/" },
    { internal: false, display: "External", url: "https://test.com" },
  ];
}
<ul>
  <li *ngFor="let link of links">
    <a *ngIf="link.internal" [routerLink]="link.url">
      <img src="/assets/icon.svg" alt="">
      <span>{{ link.display }}</span>
    </a>
    <a *ngIf="!link.internal" [attr.href]="link.url">
      <img src="/assets/icon.svg" alt="">
      <span>{{ link.display }}</span>
    </a>
  </li>
</ul>

In this method, we have two *ngIf directives on two separate a tags, and the inner content of the link is the same in both cases. If that inner content changes, we have to make the change to both places or else there are inconsistencies in the layout. This is not ideal; we are repeating ourselves and there are multiple locations where we can introduce bugs.

Solution

Angular provides a much more elegant solution to our problem. Our TypeScript code from above will remain the same, but we can have a lot less duplication in the HTML by using a couple special Angular tags. First I’ll show the HTML, and then we’ll discuss the different pieces.

<ul>
  <li *ngFor="let link of links">
    <a *ngIf="link.internal; else externalLink" [routerLink]="link.url">
      <ng-container
        [ngTemplateOutlet]="linkLayout"
        [ngTemplateOutletContext]="{ link: link }"
      ></ng-container>
    </a>
    <ng-template #externalLink>
      <a [attr.href]="link.url">
        <ng-container
          [ngTemplateOutlet]="linkLayout"
          [ngTemplateOutletContext]="{ link: link }"
        ></ng-container>
      </a>
    </ng-template>
  </li>
</ul>

<ng-template #linkLayout let-link="link">
  <img src="/assets/icon.svg" alt="" />
  <span>{{ link.display }}</span>
</ng-template>

There’s a lot going on here, so let’s break it down. We’ll start with the *ngIf on the a tag.

<a *ngIf="link.internal; else externalLink" [routerLink]="link.url">
  <ng-container
    [ngTemplateOutlet]="linkLayout"
    [ngTemplateOutletContext]="{ link: link }"
  ></ng-container>
</a>
<ng-template #externalLink>
  <a [attr.href]="link.url">
    <ng-container
      [ngTemplateOutlet]="linkLayout"
      [ngTemplateOutletContext]="{ link: link }"
    ></ng-container>
  </a>
</ng-template>

The *ngIf directive has an expression listed: if link.internal evaluates to true, then show this a tag. If it’s false, output the ng-template tag that’s referenced by the externalLink local template variable. This is how we can either navigate to a new route that’s part of the Angular app or external to the app. This is a method that can be used in any situation where your *ngIf needs an else clause.

Next up, let’s look at what’s going on with the ng-container inside both of the a tags in the example.

<ng-container
  [ngTemplateOutlet]="linkLayout"
  [ngTemplateOutletContext]="{ link: link }"
></ng-container>

You can read more about the ng-container element in the Angular docs, but at a high level it’s a special element that can hold structural directives without adding new elements to the DOM. It can also be used in situations like this, with the ngTemplateOutlet structural directive. The ngTemplateOutlet directive determines what ng-template will be output on the page inside the ng-container. The context for the template, or needed variables, can be declared with the ngTemplateOutletContext directive. In the above case, we are saying that the #linkLayout content should be output on the page, and that there should be a variable called link that will be used inside the ng-template. The contents of the ng-template tag can be placed anywhere in the HTML file, though I’ve placed them at the bottom in this example.

<ng-template #linkLayout let-link="link">
  <img src="/assets/icon.svg" alt="" />
  <span>{{ link.display }}</span>
</ng-template>

This template will be output on the screen anywhere it’s referenced. In this case, inside both a tags. If we want to change the layout inside the a tags, we need only change this one spot in the HTML. Everything will be kept in sync, and we have fewer possibilities of inconsistencies in the component.

There is one alternate way of declaring the ngTemplateOutlet. The result will be the same as the method shown above.

<ng-container
  *ngTemplateOutlet="linkLayout; context: { link: link }"
></ng-container>

Conclusion

The above method limits the duplication to a certain degree, especially for the content inside the a tag. The example here is a fairly simple layout. This method becomes more useful when the internal layout becomes more complicated. That inner layout is defined once and reused in multiple locations. You could create a new component if you wanted, but that can introduce complexity sometimes as well.

Knowing how to use ng-template, ng-container, and ngTemplateOutlet can allow you to effectively output the content of a component with minimal duplication.

Original article source at: https://www.prestonlamb.com/

#angular #ng #template 

Nico Jonsson

Nico Jonsson

1598943436

Angular Component Portals

There has been much talk and hype around Angular Ivy, with it being hailed as the saviour for many things that will come to Angular ecosystem of the future, this includes to be able to lazily load an individual component at runtime using the import syntax without the need of a NgModule itself.

this.foo = await import(`./foo.component`)
 .then(({ FooComponent }) => FooComponent);

Netanel Basal wrote an excellent post on this topic covering all the in’s and out’s on lazy loading individual components and how to use them (see link below).

Why do we want this at all? What’s all the fuss?

If you take the dashboard of a typical administration application. There are many differing aspects mostly displaying of analytical data to the user and each one of these panels can be components from various modules, but how to load these on demand or even how can the panel be customised by the end user themselves and dynamically loaded.

#angular #lazy-loading #outlet #portal #components

Extending Vue.js Components

What’s the best way to “extend” a Vue component, i.e. use one component as the basis for other components?

Doing this could save you from duplicating code, making your components quicker to develop and easier to maintain.

There are a number of APIs and patterns that Vue offers for this, and you’ll need to choose the right one depending both on your goals and personal taste.

In this article, I’ll give you an overview of the different options to help you choose the best and most suitable for your scenario.

Do you really need to extend your component?

Keep in mind that all methods of extending components can add complexity and verbosity to your code, and in some cases, additional performance overhead.

So before you decide to extend a component, it’s a good idea to first check if there are simpler design patterns that can achieve what you want.

The following component design patterns can often be sufficient substitutes for extending a component:

  • Props-driven template logic
  • Slots
  • JavaScript utility functions

Let’s do our due diligence by briefly reviewing these.

Props-driven template logic

The easiest way to make a component multi-use, and thus avoid extending it, is to provide a prop which drives conditional logic in the template.

In the following example, we use a prop type for this purpose.

<template>
  <div class="wrapper">
    <div v-if="type === 'a'">...</div>
    <div v-else-if="type === 'b'">...</div>
    <!--etc etc-->
  </div>
</template>
<script>
export default {
  props: { type: String },
  ...
}
</script>

A parent can then declare this component and use the prop to get the variation required.

<template>
  <MyVersatileComponent type="a" />
  <MyVersatileComponent type="b" />
</template>

Here are two indicators that you’ve either hit the limits of this pattern or are misusing it:

  1. The component composition model makes an app scalable by breaking down the state and logic into atomic parts. If you have too many variations in the one component (a “mega component”) you’ll find it won’t be readable or maintainable.
  2. Props and template logic are intended to make a component dynamic but come at a runtime resource cost. It’s an anti-pattern if you’re using this mechanism to solve a code composition problem at runtime.

Slots

Another way to make a component versatile without extending it is to allow the parent component to set custom content within the child using slots.

<template>
  <div class="wrapper">
    <h3>Common markup</div>
    <slot />
  </div>
</template>
<template>
  <MyVersatileComponent>
    <h4>Inserting into the slot</h4>
  </MyVersatileComponent>
</template>

Renders as:

<div class="wrapper">
  <h3>Common markup</div>
  <h4>Inserting into the slot</h4>
</div>

A potential limitation of this pattern is that the elements in the slot belong to the parent’s context, which may not be a natural way of dividing your logic and state.

Scoped slots can bring more flexibility, and we’ll explore these more in the section on renderless components.

JavaScript utility functions

If you only need to reuse standalone functions across your components, you can simply extract these into JavaScript modules without any need to use an extending pattern.

JavaScript’s module system is a very flexible and robust way of sharing code, so you should lean on it where possible.

export default function () {
  ...
}
import MyUtilityFunction from "./MyUtilityFunction";
export default {
  methods: {
    MyUtilityFunction
  }
}

#vue.js #components #composition api #renderless components #vue

Mark Mara

Mark Mara

1610801700

Build Reusable React Components with styled-components

I first used styled-components when I starting working on my first large application, and I really like how it works. It allows you to build reusable components that are easy to grow and adapt to new situations as you build different layouts.

I’m going to go over some ways you can use styled-components to make reusable components that abstract the CSS and HTML, creating your own custom component library.

#react #styled-components #javascript #reactjs