Home >Web Front-end >JS Tutorial >Angular 2 Components and Providers: Classes, Factories & Values
Core points
The previous article discussed how to use @Input
and @Output
annotations to pass data into and out of components. This article will introduce another basic aspect of Angular 2 components - their ability to use Providers.
You may have seen "providers" in the component configuration properties list, and you may realize that they allow you to define a set of injectable objects that can be used for a component. This is good, but of course it raises the question, "What is a provider?"
Answer this question requires in-depth discussion of Angular 2's dependency injection (DI) system. We may specifically cover DI in future blog posts, but a series of articles by Pascal Precht introduce this very well, starting from here: https://www.php.cn/link/f7f3bfce09a3008d185e1775549ec2d2 DI and Angular 2 DI systems (as described in Pascal's article), but in short, the DI system is responsible for:
In previous articles, we included a chart showing components forming a hierarchy that starts with the root component. Let's supplement this chart to contain the injector and its registered resources (provider):
Figure 1: Each component has its own injector for registering a provider. The injector creates a sub-injector, requests to the provider start with the local injector, and searches up the injector hierarchy.
From above we can see that although the components form a downward directional graph, their associated injectors have a bidirectional relationship: the parent injector creates a child injector (downward), when requesting the provider, if the component is The requested provider cannot be found in its own injector, Angular 2 will search up the parent injector (up). This means that providers with the same identifier at the lower level will cover (hide) providers with the same name at the higher level.
So, what are these "providers" registered by the injector at each level? It's actually very simple: the provider is Angular for providing (generating, generating) the resource or JavaScript "thing" we want to use:
Unfortunately, the term "provider" sometimes refers to both a class, function, or value, and also to something generated by the provider—a class instance, a return value or return value of a function.
Let's see how we can add providers to components by creating class providers using MyClass
(a simple class that will generate the instances we want to use in our application).
Figure 2: Simple class with four attributes. (Code screenshot from Visual Studio Code)
Okay, this is the class. Now let's instruct Angular to register the class provider using it so that we can ask the dependency injection system to provide an instance for us to use in our code. We will create a component ProvDemo_01.ts
which will be used as the root component of the application. We load this component in bootstrap.ts
and start our application:
Figure 3: Start the application's bootstrap.ts
file, which instantiates the root component.
If the above doesn't make sense, check out our previous article, which covers the process of building a simple Angular 2 application. Our root component is called ProvDemo
, and the repository contains several different versions of the component. You can change the displayed version by updating the line imported from ProvDemo
above. The first version of our root component looks like this:
Figure 4: Import MyClass
's CompDemo
, add it to the providers
array, and use it as a type in the constructor parameter.
Adding MyClass
to this component is simple to provide:
MyClass
@Component
's providers
's property MyClass
" to the constructor Behind the scenes, when Angular instantiates a component, the DI system creates an injector for the component that registers the MyClass
provider. Angular then sees the MyClass
type specified in the constructor's parameter list and looks for the newly registered MyClass
provider and uses it to generate an instance, which is then assigned to "myClass
" ( Initial lowercase "m").
The process of finding the MyClass
provider and generating the instance to be assigned to "myClass
" are both done by Angular. It uses TypeScript syntax to understand the type to search, but Angular's injector is responsible for finding and returning MyClass
instances.
In view of the above, you may conclude that Angular takes a list of classes in the "providers
" array and creates a simple registry to retrieve the class. However, for increased flexibility, there is a subtle adjustment. One of the main reasons for the need to be "tuned" is to help us write unit tests of components that have providers that we don't want to use in the test environment. There aren't many reasons not to use real things for MyClass
, but if MyClass
calls the server to retrieve data, we may not want or cannot do so in a test environment. To solve this problem, we need to be able to replace the simulation in ProvDemo
that does not make server calls. MyClass
reference to MyClass
? This is not efficient and is a bad pattern for writing tests. MyClassMock
component code. To achieve this, when Angular registers a provider, it sets up a map to associate a key (called a "token") with the actual provider. In the example above, the token and the provider are the same thing: ProvDemo
. The MyClass
attribute added to the MyClass
decorator is abbreviated for: @Component
providers
<code>providers: [ provide(MyClass, {useClass: MyClass} ]</code>as the token (key) to find the provider and setting the provider to
so that when we request the provider, the dependency injection system returns the MyClass
instance" . Most of us are used to treating keys as numbers or strings. But in this case, the token (key) is the class itself. We can also use strings as tokens to register providers as follows: MyClass
MyClass
<code>providers: [ provide("aStringNameForMyClass", {useClass: MyClass} ]</code>
This will associate the token (key)
<code>provide(MyClass, {useClass: MyClassMock}) </code>with the class provider
. When our code requires the DI system to inject MyClass
into the test, we get an instance of MyClassMock
which can forge data calls. The end effect is that all code remains the same and we don't have to worry about whether the unit test will call a server that may not exist in the test environment. MyClass
MyClassMock
Inject non-class provider
TypeScript allows us to specify that the
<code>constructor( myClass: MyClass ) {...} </code>parameter needs to be of the
type, and the DI system will do the work and provide us with myClass
instances. MyClass
But if we use string tokens instead of classes, how do we tell Angular to inject our provider results? Let's edit the bootstrap.ts
file to add a new value provider and register it with a string token. Remember that a value provider is a provider type that returns the value associated with the token. In the example above, we tell Angular to register providers by adding them to the @Component
attribute of providers
, but we can also register providers by passing them into the bootstrap function (the same content can be added to the providers
Attributes):
Figure 5: Added bootstrap.ts
of the value provider.
Here, we add the provider by calling the provide
function and passing in a string token ("SECURITY_KEY
") and an object that specifies that we want to create a value provider and the provider itself ——In this case, it is a simple value. Now we want to inject the value generated by the value provider into our constructor, but this doesn't work...
<code>providers: [ provide(MyClass, {useClass: MyClass} ]</code>
This is because "SECURITY_KEY
" is not a type. To make it possible to inject providers with non-class tokens, Angular provides us with a @Inject
parameter decorator. Like all other decorators, we need to import it, and then we use it to tell Angular to inject the provider associated with our string token. To do this, we adjust create ProvDemo_02.ts
:
Figure 6: Import the "Inject
" decorator and use it to inject the value provider identified with the string token.
We can inject the same syntax using MyClass
Provider:
<code>providers: [ provide("aStringNameForMyClass", {useClass: MyClass} ]</code>
Okay, we've learned how to register and use providers, but let's get a look at what providers return.
As we saw above, the provider is responsible for generating the things to be injected. The class provider generates an instance and injects it into it. However, it is important to understand that you don't get a new instance every time you inject the class provider result. Instead, the DI system generates an instance once, caches it, and receives the same instance for each subsequent injection every time you use the same provider.
The last point is important, because each component has its own injector and its own registered provider. MyClass
has a time attribute set to the current time (in milliseconds) and a random number to help us see if we get the same instance each time. We will add a ChildComp
component to the application.
Figure 7: Inject MyClass
into the constructor. ChildComp
and use it to set the type in the constructor parameter list. Important: The only purpose of MyClass
imported MyClass
is to be used as a token used by the DI system to find the registered provider. ChildComp
Because does not register its own provider with the token, Angular looks up the injector hierarchy to find one. In order for this to work, we need to add ChildComp
to the ChildComp
component: ProvDemo
Figure 8: 's ChildComp
was added to the template. ProvDemo
, add the ChildComp
attribute to @Component
to tell directives
we will use the ProvDemo
component and add the ChildComp
element to the template. When the application is running, the console output shows that both ChildComp
and ProvDemo
receive the same ChildComp
instance: MyClass
<code>providers: [ provide(MyClass, {useClass: MyClass} ]</code>Let's now change
to add ChildComp
to its injector Provider: MyClass
Figure 9: Defining your own provider's MyClass
. ParentComp
attribute to the @Component
annotation. Of course, we can see that two different providers
instances were created: MyClass
<code>providers: [ provide("aStringNameForMyClass", {useClass: MyClass} ]</code>This feature of Angular provides a lot of flexibility for the results generated by any provider and whether we want to use a single instance or multiple instances. For example, you can put the component in a repeater to generate the component multiple times. If this duplicate component registers its own provider, each component will get a unique provider. However, if you register a provider only in the parent component, each duplicate instance shares the provider of the parent component.
In this article, we define what a provider is and introduces three different types of providers. We then looked at how to register a provider for the component and how to inject the results generated by the provider into the component. We also looked at how Angular uses the injector hierarchy to find the requested provider. Angular gives you more control over how dependency injection systems work and where to find providers, but the above should help you get started creating and using providers in your Angular 2 application.
In Angular 2, classes are the blueprints for creating objects. It encapsulates the data and the functions that operate on that data. On the other hand, a factory is a pattern for creating objects. In Angular 2, factories are used to create and configure services or values that have no explicit classes to represent. Factory provides a way to generate different classes of instances based on context or configuration.
In Angular 2, components and providers work together to create a dynamic and interactive user interface. Components are building blocks of Angular applications, and providers are used to create services that components can use. Providers allow components to share data and functionality, making it easier to maintain and update applications.
The values in Angular 2 are used to provide configuration information to other parts of the application. They can be injected into controllers, services, and factories, allowing these parts of the application to be configured at runtime. This makes the application more flexible and easier to test.
Class binding in Angular 2 is a way to dynamically add and remove CSS classes to elements. You can bind a class to an expression, which is added to the element when the expression evaluates to true. If the expression evaluates to false, the class will be deleted. This allows you to create dynamic and interactive user interfaces.
In the context of Angular 2, API (Application Programming Interface) is a set of rules and protocols used to build and interact with software applications. Angular 2 provides a rich API that allows developers to create complex applications with less code and effort. The Angular 2 API includes features for creating components, services, instructions, pipelines, and more.
To use a factory in Angular 2, you first need to define it. This is done by creating a function that returns the object you want the factory to generate. You can then register this factory with the Angular module using the .factory
method. Once the factory is registered, you can inject it into other parts of the application, such as controllers and services.
Creating a component in Angular 2 involves defining a class and decorating it using the @Component
decorator. @Component
The decorator tells Angular that the class is a component and provides metadata that determines how the component is processed, instantiated, and used at runtime.
The provider in Angular 2 is used to create and provide services to the application section. To use a provider, you first need to register it with the Angular module. After registration, the provider can be injected into components, other services, and even other providers.
Creating a service in Angular 2 involves defining a class that encapsulates the numbers and functions provided by the service. This class will then be decorated with a @Injectable
decorator which tells Angular that the class is a service that can be injected into other parts of the application.
The values in Angular 2 are used to provide configuration information to other parts of the application. To use a value, you first need to register it with the Angular module. After registration, the value can be injected into the controller, the service, and the factory.
The above is the detailed content of Angular 2 Components and Providers: Classes, Factories & Values. For more information, please follow other related articles on the PHP Chinese website!