Подтвердить что ты не робот

Как объявить класс модели в моем компоненте Angular 2 с помощью TypeScript?

Я новичок в 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) {}
}
4b9b3361

Ответ 1

Я бы попробовал это:

Разделите вашу модель в отдельный файл с именем model.ts:

export class Model {
    param1: string;
}

Импортируйте его в свой компонент. Это даст вам дополнительное преимущество возможности использовать его в других компонентах:

Import { Model } from './model';

Инициализируйте в компоненте:

export class testWidget {
   public model: Model;
   constructor(){
       this.model = new Model();
       this.model.param1 = "your string value here";
   }
}

Доступ к нему соответствующим образом в HTML:

@Component({
      selector: "testWidget",
      template: "<div>This is a test and {{model.param1}} is my param.</div>"
})

Я хочу добавить к ответу комментарий, сделанный @PatMigliaccio, потому что важно адаптировать его к последним инструментам и технологиям:

Если вы используете angular-cli вы можете вызвать ng g class model и она сгенерирует ее для вас. модель заменяется на любое имя, которое вы пожелаете.

Ответ 2

Проблема заключается в том, что вы не добавили 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() {}
}

Ответ 3

В вашем случае у вас есть модель на той же странице, но вы ее объявили после своего класса Component, так что вам нужно использовать forwardRef для ссылки на Class. Не рекомендуется делать это, всегда иметь объект model в отдельном файле.

export class testWidget {
    constructor(@Inject(forwardRef(() => Model)) private service: Model) {}
}

Кроме того, вам нужно изменить интерполяцию вида, чтобы ссылаться на правильный объект

{{model?.param1}}

Лучше всего вам нужно сделать, вы можете определить свой класс model в другом файле, а затем импортировать его как когда вам это нужно. Также перед введите export, чтобы вы могли импортировать его.

import { Model } from './model';

Ответ 4

мой код

    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>

Ответ 5

Вы можете использовать angular-cli, как предлагают комментарии в ответе @brendon.

Вы также можете попробовать:

ng g class modelsdirectory/modelName --type=model

/* will create
 src/app/modelsdirectory
 ├── modelName.model.ts
 ├── ...
 ...
*/

Имейте в виду: ng g class ! == ng gc
Тем не менее, вы можете использовать ng g cl качестве ярлыка в зависимости от вашей версии angular-cli.

Ответ 6

Я понимаю, что это несколько более старый вопрос, но я просто хотел указать, что вы неправильно добавили переменную модели в свой класс тестовых виджетов. Если вам нужна переменная Model, вам не следует пытаться передать ее через конструктор компонента. Вы только собираетесь передавать услуги или другие виды инъекций таким образом. Если вы создаете экземпляр тестового виджета внутри другого компонента и вам необходимо передать объект модели как, я бы порекомендовал использовать шаблоны проектирования OnInit и Input/Output углового ядра.

Например, ваш код должен выглядеть примерно так:

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 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 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 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. Если бы он был предоставлен на уровне модуля, у вас был бы только один экземпляр, общий для всех компонентов и служб в этом модуле.

Вместо этого вы должны следовать стандартным объектно-ориентированным методам и создавать частную переменную модели как часть класса, и если вам нужно передавать информацию в эту модель при создании экземпляра экземпляра, то она должна обрабатываться службой (инъекционной), предоставляемой родительский модуль. Таким образом, ввод зависимостей и коммуникация должны выполняться под углом.

Кроме того, как некоторые другие упоминали, вы должны объявить ваши классы модели в отдельном файле и импортировать класс.

Я настоятельно рекомендую вернуться к справочнику по угловой документации и просмотреть основные страницы по различным аннотациям и типам классов: https://angular.io/guide/architecture

Вы должны обратить особое внимание на разделы, посвященные модулям, компонентам и услугам/внедрению зависимостей, поскольку они необходимы для понимания того, как использовать Angular на архитектурном уровне. Angular - это очень тяжелый архитектурный язык, потому что это очень высокий уровень. Разделение задач, фабрики внедрения зависимостей и управление версиями javascript для сопоставимости браузера в основном выполняются за вас, но вы должны правильно использовать их архитектуру приложения, иначе вы обнаружите, что все работает не так, как вы ожидаете.

Ответ 7

export class Car {
  id: number;
  make: string;
  model: string;
  color: string;

  constructor(car) {
      {
        this.id = car.id;
        this.make = car.make || '';
        this.model = car.model || '';
        this.color = car.color || '';
      }
  }
}

В вашем файле 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));