Angular ngFor - Learn all Features including trackBy, why is it not only for Arrays ? Also, the focus functionality is missing. This is a pretty natural choice for implementing this component, and it's likely the design we could come up on a first attempt.
This is the initial implementation of our component: Try to guess what is the biggest problem of this design, while we break down this implementation step-by-step. As we have seen, it's as important to know how the ng-content core directive works, as to know the typical scenarios and use cases on which we would like to use it. But if we start using this component in our application, we will quickly run into a series of problems. The ng-content core directive allows for component designs where certain internal details of the template are not hidden inside the component but instead are provided as an input, which in certain cases really simplifies the design. Let's then create a directive named inputRef, and apply it to the HTML Input: We will take the opportunity to use that same directive to track if the input has the focus or not: Here is what is going on in this directive: We can now use this directive and have it injected inside the Font Awesome Input component, effectively allowing us to interact with projected content! Such as for example the keydown event? As we can see on the template, the main idea is that the component is made of an icon and a plain HTML input.
and that is the root cause of all the design problems listed above!
While building forms, third party systems might expect certain HTML custom data- properties to be filled in, for scenarios where a full page submission occurs (instead of sending an Ajax request). The current input styles look like this, and we can find them inside the fa-input.component.css file: Here is why this does not work anymore: because these styles sit inside a file linked to the component, they will have applied at startup time an attribute that is unique to all the HTML elements inside that particular component template: So what is this strange identifier?
Also, this new version has accidentally created a new problem - have a look at the input box now: Do you notice the duplicate border? So this shows how to style projected content if necessary. Typescript 2 Type Definitions Crash Course - Types and Npm, how are they linked ? Let's now say that we would like to project not only the HTML input itself, but also the icon inside the input. For example, this would also inject the input element into the template: In this context, the
We cannot interact with the ng-content tag, and for example define event listeners on top of it. This is also possible using content projection.
of the features presented here solve several long-term, Angular ng-content and Content Projection: A Complete Guide - How To Use ng-content To Improve Component API Design, Angular Router - How To Build a Navigation Menu with Bootstrap 4 and Nested Routes, Angular Router - Extended Guided Tour, Avoid Common Pitfalls, How to build Angular apps using Observable Data Services - Pitfalls to avoid, Introduction to Angular Forms - Template Driven vs Model Driven. third-party library.
It looks the styling that we had put in place to remove the border from the HTML input is not working anymore!
Let's have a look at the runtime HTML on the page for our component: This is a simplified version of the HTML, that helps better understand what is going on: In order to style the projected input and remove the double border, we need to change the styles to something like this: So how do these new styles work? This type of API is actually very common in several standard HTML elements, such as for example select boxes or lists: Angular Core does allow us to do something similar in our components! So what is the major problem with this component design?
This would be quite cumbersome but still doable. Let's first see how the component would be used: So as we can see, the component is a custom HTML element named fa-input, that takes as input an icon name, and outputs the values of the text box. One of the Angular features that help us the most in building reusable components is Content Projection and ng-content. In the content part of the the fa-input tag we can put multiple types of content, for example: We can then consume the different types of content available inside the fa-input tag, by using the select property of ng-content: These two selectors are looking for a particular element type (an input or an icon tag), but we could also look for an element with a given CSS class, and combine multiple selectors. But now, we get into a situation for which we don't have a good workaround for.
So how does this work? What Problem is Content Projection Trying to Solve? Let's take this very common HTML pattern and make it available as an Angular component. It looks like despite the several problems that we have solved by using ng-content, we still have at this point two major questions about it: Let's start by understanding why the styles we had in place no longer work with ng-content. The good news is that using content projection we will be able to support all these use cases, and much more. Instead of hiding the input element inside the component, let's provide it as a content element of the component itself: Notice that we did not provide the form text field as a component input property. We are going to list here 4 of them, starting with: Our component is meant to be used in place of a plain HTML input, but it does not support any of its standard properties. Before going over the component class implementation, let's have a look at its styling: Let's go back to the component class and see how all the pieces of the puzzle are glued together: And this implementation does work!
But what if we would like to project only part of it?
This would be quite cumbersome but still doable. This video list will help you get a good overview of the language, because some
As we know, normal HTML inputs cannot display an image. In that case, we would have to also forward all the form properties such as for example formControlName to the plain input as well. Let's break this down: To see how this works in practice, this is the actual CSS at runtime: So as we can see, the styles are still scoped to the component only, but they will leak through to any inputs inside the component at runtime: including the projected HTML input!
To be able to simulate the focus functionality, we need the fa-input input component to know that the projected input focus was either activated or blurred.
For example, this is a plain input of type email with autocompletion turned off and a placeholder: All these standard browser properties are not supported by our component, and these are only a few of the properties that have this problem. But there are several major problems with this design, let's have a look at how the component was implemented to understand why, and then see how Content Projection will provide a clean solution for those issues.
For example, have a look at the following text boxes: Notice that with the presence of both the icon and the text placeholder, we hardly need to have also the field label to the left, which is especially useful on mobile.