Я новичок в Angular 2 и TypeScript и стараюсь следовать лучшим практикам.
Вместо использования простой модели JavaScript ({}) я пытаюсь создать класс TypeScript.
Однако Angular 2 это, похоже, не нравится.
Мой код:
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;
}
и я использую его как:
import { testWidget} from "lib/testWidget";
@Component({
selector: "myComponent",
template: "<testWidget></testWidget>",
directives: [testWidget]
})
Я получаю сообщение об ошибке от Angular:
ИСКЛЮЧЕНИЕ: Невозможно разрешить все параметры для testWidget: (?).
Вот я и подумал: Модель еще не определена ... Перемещу наверх!
Вот только теперь я получаю исключение:
ОРИГИНАЛЬНОЕ ИСКЛЮЧЕНИЕ: нет поставщика для модели!
Как мне этого добиться?
Изменить: Спасибо всем за ответ. Это привело меня на правильный путь.
Чтобы вставить это в конструктор, мне нужно добавить его к поставщикам компонента.
Кажется, это работает:
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) {}
}
источник
providers: [Model]
. Также, согласно демонстрации Angular 2 Tour of Hero, вы должны просто использовать его как свойство, а не как инъекцию, поскольку эта функциональность обычно зарезервирована для более сложных классов, таких как службы.new
). Разве что конструктора модели не назовут. И этоinstanceOf Model
будет ложьюnew
на днях, и мне он нравится в таких простых случаях, как этот.angular-cli
вы можете позвонить,ng g class model
и он сгенерирует его для вас.model
заменяется любым именем, которое вы пожелаете.Проблема в том, что вы не добавили
Model
ни вbootstrap
(что сделает его одноэлементным), ни вproviders
массив определения вашего компонента:@Component({ selector: "testWidget", template: "<div>This is a test and {{param1}} is my param.</div>", providers : [ Model ] }) export class testWidget { constructor(private model: Model) {} }
И да, вы должны определить
Model
вышеComponent
. Но лучше было бы поместить его в свой файл.Но если вы хотите, чтобы это был просто класс, из которого вы можете создавать несколько экземпляров, вам лучше просто использовать
new
.@Component({ selector: "testWidget", template: "<div>This is a test and {{param1}} is my param.</div>" }) export class testWidget { private model: Model = new Model(); constructor() {} }
источник
providers
массиве?No Provider for Model
если не добавляю его в массив провайдеровexport
перед урокомModel
?В вашем случае у вас есть модель на той же странице, но она объявлена после вашего класса Component, поэтому вам нужно использовать
forwardRef
для ссылкиClass
. Не предпочитаю это делать, всегда хранитеmodel
объект в отдельном файле.export class testWidget { constructor(@Inject(forwardRef(() => Model)) private service: Model) {} }
Кроме того, вы должны изменить интерполяцию просмотра, чтобы ссылаться на правильный объект
Лучше всего, что вы должны сделать, вы можете определить свой
Model
класс в другом файле, а затем импортировать его, когда вам это нужно. Такжеexport
укажите имя класса, чтобы его можно было импортировать.import { Model } from './model';
источник
мой код
import { Component } from '@angular/core'; class model { username : string; password : string; } @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { username : string; password : string; usermodel = new model(); login(){ if(this.usermodel.username == "admin"){ alert("hi"); }else{ alert("bye"); this.usermodel.username = ""; } } }
и html выглядит так:
<div class="login"> Usernmae : <input type="text" [(ngModel)]="usermodel.username"/> Password : <input type="text" [(ngModel)]="usermodel.password"/> <input type="button" value="Click Me" (click)="login()" /> </div>
источник
export class Car { id: number; make: string; model: string; color: string; year: Date; constructor(car) { { this.id = car.id; this.make = car.make || ''; this.model = car.model || ''; this.color = car.color || ''; this.year = new Date(car.year).getYear(); } } }
|| может стать очень полезным для очень сложных объектов данных вместо данных по умолчанию, которые не существуют.
. .
В файле component.ts или service.ts вы можете десериализовать данные ответа в модель:
// Import the car model import { Car } from './car.model.ts'; // If single object car = new Car(someObject); // If array of cars cars = someDataToDeserialize.map(c => new Car(c));
источник
Вы можете использовать angular-cli, как предлагают комментарии в ответе @ brendon.
Вы также можете попробовать:
ng g class modelsDirectoy/modelName --type=model /* will create src/app/modelsDirectoy ├── modelName.model.ts ├── ... ... */
Имейте в виду
ng g class
:! ==ng g c
Однако вы можете использовать в
ng g cl
качестве ярлыка в зависимости от вашей версии angular-cli.источник
Я понимаю, что это несколько более старый вопрос, но я просто хотел указать, что вы неправильно добавили переменную модели в свой тестовый класс виджета. Если вам нужна переменная модели, вы не должны пытаться передать ее через конструктор компонента. Вы должны только таким образом передавать услуги или другие типы инъекций. Если вы создаете экземпляр своего тестового виджета внутри другого компонента и вам нужно передать объект модели как, я бы рекомендовал использовать шаблоны проектирования OnInit и Input / Output ядра angular.
Например, ваш код действительно должен выглядеть примерно так:
import { Component, Input, OnInit } from "@angular/core"; import { YourModelLoadingService } from "../yourModuleRootFolderPath/index" class Model { param1: string; } @Component({ selector: "testWidget", template: "<div>This is a test and {{model.param1}} is my param.</div>", providers: [ YourModelLoadingService ] }) export class testWidget implements OnInit { @Input() model: Model; //Use this if you want the parent component instantiating this //one to be able to directly set the model's value private _model: Model; //Use this if you only want the model to be private within //the component along with a service to load the model's value constructor( private _yourModelLoadingService: YourModelLoadingService //This service should //usually be provided at the module level, not the component level ) {} ngOnInit() { this.load(); } private load() { //add some code to make your component read only, //possibly add a busy spinner on top of your view //This is to avoid bugs as well as communicate to the user what's //actually going on //If using the Input model so the parent scope can set the contents of model, //add code an event call back for when model gets set via the parent //On event: now that loading is done, disable read only mode and your spinner //if you added one //If using the service to set the contents of model, add code that calls your //service's functions that return the value of model //After setting the value of model, disable read only mode and your spinner //if you added one. Depending on if you leverage Observables, or other methods //this may also be done in a callback } }
Класс, который по сути является просто структурой / моделью, не должен вводиться, потому что это означает, что у вас может быть только один общий экземпляр этого класса в пределах предоставленной области. В этом случае это означает, что один экземпляр Model создается инжектором зависимостей каждый раз, когда создается экземпляр testWidget. Если бы он был предоставлен на уровне модуля, у вас был бы только один экземпляр, совместно используемый всеми компонентами и службами в этом модуле.
Вместо этого вы должны следовать стандартным методам объектно-ориентированной модели и создавать частную переменную модели как часть класса, и если вам нужно передать информацию в эту модель при создании экземпляра, это должно обрабатываться службой (вводимой), предоставляемой родительский модуль. Таким образом и внедрение зависимостей, и коммуникация должны выполняться в angular.
Кроме того, как уже упоминалось, вы должны объявлять классы своей модели в отдельном файле и импортировать этот класс.
Я настоятельно рекомендую вернуться к справочной документации по angular и просмотреть основные страницы по различным аннотациям и типам классов: https://angular.io/guide/architecture
Вам следует обратить особое внимание на разделы, посвященные модулям, компонентам и службам / внедрению зависимостей, поскольку они необходимы для понимания того, как использовать Angular на архитектурном уровне. Angular - это язык с очень тяжелой архитектурой, потому что он очень высокого уровня. Разделение проблем, фабрики внедрения зависимостей и управление версиями javascript для сопоставимости браузеров в основном обрабатываются за вас, но вы должны правильно использовать их архитектуру приложений, иначе вы обнаружите, что все работает не так, как вы ожидаете.
источник
создайте model.ts в каталоге компонентов, как показано ниже
export module DataModel { export interface DataObjectName { propertyName: type; } export interface DataObjectAnother { propertyName: type; } }
затем в импорте компонента выше как, импортируйте {DataModel} из './model';
export class YourComponent { public DataObject: DataModel.DataObjectName; }
ваш DataObject должен иметь все свойства из DataObjectName.
источник