Как получить ссылку на компонент, связанный с ElementRef в Angular 2
У меня есть этот компонент в моем шаблоне:
<vector-editor #scaleControl
[x]="scaleX"
[y]="scaleY"
[z]="scaleZ" >
</vector-editor>
vector-editor
имеет следующую структуру:
export class VerticeControlComponent implements OnInit
{
@Input() x: number;
@Input() y: number;
@Input() z: number;
...
}
В моем приложении я получаю ссылку на #scaleControl
с помощью
@ViewChild('scaleControl') scaleControl: ElementRef;
Теперь, если я выведу scaleControl
в консоль я получаю такой результат:
Как видно, ссылка не является нулевой, и все свойства моего компонента есть. Я хочу получить доступ к этим свойствам, но в коде фактический тип scaleControl
является ElementRef
и не VectorEditorControl
как видно на выходе. Из-за этого TypeScript не позволяет мне использовать this.scaleControl.x
,
Я также пытался бросить ElementRef
как это
var temp = <VectorEditorControl>this.scaleControl
но я получаю сообщение о том, что не могу разыграть ElementRef
в VectorEditorControl
В конце концов я попытался получить доступ this.scaleControl.nativeElement
но это не определено...
Что мне здесь не хватает?
3 ответа
Вы должны знать следующее об использовании декоратора свойств @ViewChild.
Он использует следующие свойства метаданных:
- селектор - тип директивы или имя, используемое для запроса.
- читать - читать другой токен из запрашиваемых элементов.
Из исходного кода:
export interface ViewChildDecorator {
/**
* You can use ViewChild to get the first element or the directive matching
* the selector from the
* view DOM. If the view DOM changes, and a new child matches the selector,
* the property will be updated.
*
* View queries are set before the `ngAfterViewInit` callback is called.
*
* **Metadata Properties**:
*
* * **selector** - the directive type or the name used for querying.
* * **read** - read a different token from the queried elements.
*/
(selector: Type<any>|Function|string, {read}?: {read?: any}): any;
new (selector: Type<any>|Function|string, {read}?: {read?: any}): ViewChild;
}
Если вы не предоставите read
параметр, @ViewChild()
вернет:
- экземпляр компонента, если есть.
ElementRef
экземпляр, если не применен компонент- отличается от токена запрашиваемых элементов, если вы установили свойство read
Так что если вы хотите получить ElementRef
от ребенка, который является компонентом angular2 (VerticeControlComponent
) вам нужно явно сказать, используя read: ElementRef
:
@ViewChild('scaleControl', {read: ElementRef}) scaleControl: ElementRef;
И тогда внутри хука ngAfterViewInit или позже вы можете написать this.scaleControl.nativeElement
чтобы получить элемент DOM.
Обновить
Я написал рано:
- отличается от токена запрашиваемых элементов, если вы установили свойство read
Теперь я хочу добавить, что именно мы можем прочитать:
ElementRef
TemplateRef
ViewContainerRef
поставщик
Что значит Provider
значит здесь?
Это означает, что если мы определили какого-либо поставщика (в компоненте или директиве) для конкретного элемента, то мы можем прочитать его.
@Component({
selector: 'child',
template: `
<h2>I'm child</h2>
`,
providers: [
{
provide: 'test', useValue: 'x'
}
]
})
export class ChildComponent {
}
Таким образом, в потребителя этого компонента мы можем написать
@ViewChild(ChildComponent, { read: 'test' }) providerToken: string;
чтобы получить ценность x
,
Смотрите также:
На момент написания я рекомендую использовать следующий метод:
@ViewChild('scaleControl') scaleControl: ElementRef<VerticeControlComponent>;
Затем вы можете получить доступ к обоим типам.
- ElementRef: использование
scaleControl
- VerticeControlComponent: использование
scaleControl.nativeElement
Я получил эту ошибку два раза. Один раз в моем основном коде и второй раз в тестовом коде (спецификации).
Оба раза не хватало ссылок. Угловой компилятор (транспортер) не показывает никаких ошибок во время компиляции, но позже спокойно не предоставляет ссылку на
Впервые я получил эту ошибку в основном коде abc.component.ts. Я помню, что на этот раз мы правильно включили ссылки, необходимые для этого ребенка, в этот abc.component.ts. Этот дочерний компонент был из другого модуля. Ошибка была устранена только после того, как этот дочерний компонент не был включен в файл module.ts
объявления: [VectorEditorComponent,....],
Второй раз мы столкнулись с этим в spec-файле. Я пытался проверить некоторые ожидания, что свойство дочернего компонента должно быть установлено. Я не получал экземпляр дочернего компонента, а вместо этого получал ElementRef. Здесь снова не было ошибки компиляции. Проблема была немного другой здесь. Я использовал No_Errors_Schema. Итак, хотя мы не включили компонент в файл спецификаций, angular не жаловался, а вместо этого установил ElementRef вместо дочернего компонента. Ошибка исчезла, когда мы импортировали модуль и предоставили это в настройках тестового стенда в файле спецификации.
Во втором случае я могу понять, что это произошло из-за ошибки схемы. Но в первом случае, я думаю, Angular команда нуждается в улучшении. Нет никаких намеков на то, почему компонент не был предоставлен, но предоставляется ElementRef.