I am new to Angular 2 and TypeScript and I'm trying to follow best practices.
Instead of using a simple JavaScript model ({ }), I'm attempting to create a TypeScript class.
However, Angular 2 doesn't seem to like it.
My code is:
import { Component, Input } from "@angular/core";
@Component({
selector: "testWidget",
template: "<div>This is a test and {{model.param1}} is my param.</div>"
})
export class testWidget {
constructor(private model: Model) {}
}
class Model {
param1: string;
}
and I'm using it as:
import { testWidget} from "lib/testWidget";
@Component({
selector: "myComponent",
template: "<testWidget></testWidget>",
directives: [testWidget]
})
I'm getting an error from Angular:
EXCEPTION: Can't resolve all parameters for testWidget: (?).
So I thought, Model isn't defined yet... I'll move it to the top!
Except now I get the exception:
ORIGINAL EXCEPTION: No provider for Model!
How do I accomplish this??
Edit: Thanks to all for the answer. It led me to the right path.
In order to inject this into the constructor, I need to add it to the providers on the component.
This appears to work:
import { Component, Input } from "@angular/core";
class Model {
param1: string;
}
@Component({
selector: "testWidget",
template: "<div>This is a test and {{model.param1}} is my param.</div>",
providers: [Model]
})
export class testWidget {
constructor(private model: Model) {}
}
In your case you are having model on same page, but you have it declared after your Component class, so that's you need to use
forwardRef
to refer toClass
. Don't prefer to do this, always havemodel
object in separate file.Additionally you have to change you view interpolation to refer to correct object
Better thing you should do is, you can have your
Model
Class define in different file & then import it as an when you require it by doing. Also haveexport
before you class name, so that you can import it.You can use the angular-cli as the comments in @brendon's answer suggest.
You might also want to try:
Bear in mind:
ng g class
!==ng g c
However, you can use
ng g cl
as shortcut depending on your angular-cli version.The problem lies that you haven't added
Model
to either thebootstrap
(which will make it a singleton), or to theproviders
array of your component definition:And yes, you should define
Model
above theComponent
. But better would be to put it in his own file.But if you want it to be just a class from which you can create multiple instances, you better just use
new
.I realize this is a somewhat older question, but I just wanted to point out that you've add the model variable to your test widget class incorrectly. If you need a Model variable, you shouldn't be trying to pass it in through the component constructor. You are only intended to pass services or other types of injectables that way. If you are instantiating your test widget inside of another component and need to pass a model object as, I would recommend using the angular core OnInit and Input/Output design patterns.
As an example, your code should really look something like this:
A class which is essentially just a struct/model should not be injected, because it means you can only have a single shared instanced of that class within the scope it was provided. In this case, that means a single instance of Model is created by the dependency injector every time testWidget is instantiated. If it were provided at the module level, you would only have a single instance shared among all components and services within that module.
Instead, you should be following standard Object Oriented practices and creating a private model variable as part of the class, and if you need to pass information into that model when you instantiate the instance, that should be handled by a service (injectable) provided by the parent module. This is how both dependency injection and communication is intended to be performed in angular.
Also, as some of the other mentioned, you should be declaring your model classes in a separate file and importing the class.
I would strongly recommend going back to the angular documentation reference and reviewing the basics pages on the various annotations and class types: https://angular.io/guide/architecture
You should pay particular attention to the sections on Modules, Components and Services/Dependency Injection as these are essential to understanding how to use Angular on an architectural level. Angular is a very architecture heavy language because it is so high level. Separation of concerns, dependency injection factories and javascript versioning for browser comparability are mainly handled for you, but you have to use their application architecture correctly or you'll find things don't work as you expect.
I'd try this:
Split your Model into a separate file called
model.ts
:Import it into your component. This will give you the added benefit of being able to use it in other components:
Initialize in the component:
Access it appropriately in the html:
I want to add to the answer a comment made by @PatMigliaccio because it's important to adapt to the latest tools and technologies:
my code is
and the html goes like this :