Angular 2의 동적 템플릿 URL
나는 지난 며칠 동안 Angular 2를 가지고 놀았고 역동적인 것을 제공하는 것이 가능한지 궁금했습니다.templateUrl
에게@View
장식가
함수를 전달하고 문자열을 반환하려고 했지만 전체 함수가 문자열로 바뀌었습니다.
저도 Angular 1.x를 사용해 본 적이 없어서 잘못된 방식으로 진행하는 것인지 모르겠지만, 이것이 가능한가요, 아니면 동적 뷰를 만드는 더 나은 방법이 있나요?
예를 들어 사용자가 로그인하지 않은 경우 양식을 표시하고 로그인한 경우 텍스트 메시지를 표시할 수 있습니다.
다음과 같은 것이 작동하지 않습니다.
@Component({
selector: 'my-component'
})
@View({
// This doesn't work
templateUrl: function() {
return this.isLoggedIn ? 'logged-in.html' : 'logged-out.html';
}
})
class MyComponent {
constructor() {
this.loggedIn = false;
}
}
어떤 도움이라도 주시면 감사하겠습니다.
가장 우아한 솔루션은 아니지만 DynamicComponentLoader 및 ElementRef를 사용하여 구성 요소에 템플릿 값을 동적으로 할당했습니다.사실 저는 여러 사용자 정의 구성요소를 플레이스홀더에 추가할 수 있는 솔루션을 찾고 있었습니다.
shmck에서 설명한 기능으로 서비스 인젝션을 시도해 보았습니다. 템플릿 기능이 호출되었을 때 아직 서비스를 이용할 수 없기 때문에 이것은 작동하지 않습니다.실제로.this
Window 개체를 나타냅니다.
내가 사용한 솔루션에 대한 참조 URL은 다음에서 찾을 수 있습니다: ComponentResolver 및 Angular2에서 ngFor를 사용하여 동적 anchorName/Components 만들기
저는 또한 이 방법을 Plnkr1과 Plnkr2로 참조합니다.
Dartdocs 사이트는 TypeScript에도 적용 가능한 Angular 2 Dynamic ComponentLoader 클래스에 대한 훌륭한 문서를 제공합니다.
간단히 말해서:
사용할 템플릿으로서의 단순 구성요소
@Component({
selector: 'dt2-simple-block',
properties: ["idx"],
template: `<h1>Simple block for {{ idx }} </h1>`,
directives: []
})
class dt2SimpleBlock {
constructor() {
}
}
추가할 모든 구성 요소를 보유하는 구성 요소의 생성자(내 앱에는 여러 자식이 포함되어야 함:
constructor(loader: DynamicComponentLoader, elementRef: ElementRef) {
//iterate
for (var i = 0; i < toSomething; i++) {
// build the template
var blockdirective = 'dt2-simple-block'
var template = '<' + blockdirective +
' idx="' + this.userBlocks.userHomePanelBlocks[i] +
'"></' + blockdirective + '>';
console.log(template); // debugging purpose
var directives = [dt2SimpleBlock];
loader.loadNextToLocation(toComponent(template, directives), elementRef);
}
그리고 도우미 기능은 유용하게 쓰일 것입니다.
function toComponent(template, directives = []) {
@Component({ selector: 'fake-component' })
@View({ template, directives })
class FakeComponent { }
return FakeComponent;
}
내 솔루션:
class myViewResolver extends ViewResolver{
resolve(component: Type): ViewMetadata {
var view = super.resolve(component);
// TODO: Write logic here:-)
view.templateUrl = 'app/app.html';
return view;
}
}
bootstrap(App,[
provide(ViewResolver , {useClass:myViewResolver})
]);
요청하신 내용은 아니지만, 다음과 같이 언급할 가치가 있습니다.
대부분의 사용 사례에서 작동하는 또 다른 간단한 솔루션은 다음과 같이 논리를 템플릿 자체에 넣는 것입니다.
@Component({
selector: 'my-component'
})
@View({
// Note1: Here, I use template instead of templateUrl.
// Note2: I use ES6 string interpolation + require() to embed/load the other templates, but you can do it however you like.
template: `
<div [ngSwitch]="loggedIn">
<template [ngSwitchCase]="true"> ${require('./logged-in.html')} </template>
<template ngSwitchDefault> ${require('./logged-out.html')} </template>
</div>`
})
class MyComponent {
constructor() {
this.loggedIn = false;
}
}
이 솔루션의 단점은 제공된 Js 파일에 두 템플릿이 모두 포함되어 있기 때문에 큰 템플릿에 문제가 될 수 있다는 것입니다. 그러나 실제로 렌더링되는 템플릿은 하나뿐이며 대부분의 경우 js 크기 오버헤드가 허용됩니다.
내 솔루션:(이것의 장점은 HTML과 CSS 파일을 느리게 로딩하는 것입니다.)
여기는 home.componet.ts입니다.
import { Component } from '@angular/core';
import { DynamicHTMLOutlet } from './../../directives/dynamic-html-outlet/dynamicHtmlOutlet.directive';
import { TranslateService, LangChangeEvent } from 'ng2-translate/ng2-translate';
@Component({
selector: 'lib-home',
templateUrl: './app/content/home/home.component.html',
directives: [DynamicHTMLOutlet]
})
export class HomeComponent {
html_template = `./app/content/home/home_`;
html: string;
css: string;
constructor(translate: TranslateService) {
this.html = this.html_template + translate.currentLang;
this.css = './app/content/home/home.component.css';
translate.onLangChange.subscribe((event: LangChangeEvent) => {
this.html = this.html_template + translate.currentLang;
this.css = './app/content/home/home.component.css';
});
}
}
내가 사용한 지침과 몇 가지 변경 사항:이것은 home.componnet.html에 있습니다.
<dynamic-html-outlet [htmlPath]="html" [cssPath]="css"></dynamic-html-outlet>
동적 구성 요소에 대한 지침은 다음과 같습니다.
import {
Component,
Directive,
ComponentFactory,
ComponentMetadata,
ComponentResolver,
Input,
ReflectiveInjector,
ViewContainerRef,
} from '@angular/core';
import { TranslatePipe } from 'ng2-translate/ng2-translate';
declare var $:any;
export function createComponentFactory(resolver: ComponentResolver, metadata: ComponentMetadata): Promise<ComponentFactory<any>> {
const cmpClass = class DynamicComponent {};
const decoratedCmp = Component(metadata)(cmpClass);
return resolver.resolveComponent(decoratedCmp);
}
@Directive({
selector: 'dynamic-html-outlet',
})
export class DynamicHTMLOutlet {
@Input() htmlPath: string;
@Input() cssPath: string;
constructor(private vcRef: ViewContainerRef, private resolver: ComponentResolver) {
}
ngOnChanges() {
if (!this.htmlPath) return;
$('dynamic-html') && $('dynamic-html').remove();
const metadata = new ComponentMetadata({
selector: 'dynamic-html',
templateUrl: this.htmlPath +'.html',
styleUrls: [this.cssPath],
pipes: [TranslatePipe]
});
createComponentFactory(this.resolver, metadata)
.then(factory => {
const injector = ReflectiveInjector.fromResolvedProviders([], this.vcRef.parentInjector);
this.vcRef.createComponent(factory, 0, injector, []);
});
}
}
"ng serve --aot"를 사용하여 응용 프로그램을 컴파일합니다.
export let DEFAULT_PREFIX :string= './app.component';
//or localStorage.getItem('theme')
export function getMySuperTemplate(template: string) {
return DEFAULT_PREFIX + template + '.html';
}
@Component({
selector: 'app-root',
templateUrl: getMySuperTemplate('2'),
styleUrls:['./app.component.css']
})
@Eyal Vardi의 답변으로 업데이트 (ViewResolver
사용되지 않음):
import { Directive, Type, Component } from '@angular/core';
import { DirectiveResolver } from '@angular/compiler';
class myViewUrlResolver extends DirectiveResolver {
resolve(type: Type<any>, throwIfNotFound?: boolean): Directive {
let view = <any>super.resolve(type, throwIfNotFound);
if (typeof view["templateUrl"] !== "undefined") {
console.log("Yay!");
let originalUrl = (<Component>view).templateUrl;
(<Component> view).templateUrl = environment.nativeScriptAppPrePathPrefix + originalUrl.replace(".html", ".tns.html");
}
if (typeof view["styleUrls"] !== "undefined") {
console.log("Yay2!");
let originalUrls = (<Component>view).styleUrls;
originalUrls.forEach((originalUrl, at) => (<Component>view).styleUrls[at] = environment.nativeScriptAppPrePathPrefix + originalUrl.replace(".html", ".tns.css"));
}
return view;
}
}
platformNativeScriptDynamic().bootstrapModule(AppModule,{
providers: [
{ provide: DirectiveResolver, useClass: myViewUrlResolver }
]
});
보안 문제로 인해 Angular 2에서는 동적 템플릿을 만드는 이 방법을 사용할 수 없습니다.안타깝게도 Angular 1에서 이전 애플리케이션이 동적으로 이러한 방식으로 구동되었습니다.
각도 2의 경우 - 동일한 작업을 수행하는 다른 방법일 수 있습니다(아래 링크 예제).템플릿 html 파일을 응용프로그램의 구성요소로 업데이트한 다음 (문자열을 사용하여 templateUrl을 만들려는 위치 등)에 주입하면 구성요소 템플릿 매개변수를 요소로 볼 수 있습니다(DynamicComponentLoader 사용).
https://angular.io/docs/js/latest/api/core/DynamicComponentLoader-class.html
호프, 당신을 위한 허브 예시가 당신을 도울 것입니다!동적 html을 컴파일하는 예가 있습니다.따라서 서비스별로 HTML을 로드한 다음 컴파일할 수 있습니다.
1- 이 라이브러리 설치
npm i-D html 로더
============================================================
2 - webpack.config에서 html 파일에 html-loader 사용
{ test: /\.html$/, loaders: ['html-loader'] }
============================================================
3- ionic을 사용하는 경우 "node_modules/@ionic/app-scripts/config/webpack.config.js" 경로에서 webpack.config.js를 복사한 다음 html 로더를 추가할 수 있습니다.
=============================================================
4-아이오닉 인 패키지를 사용하는 경우.json 이 줄들을 추가합니다.
"config": {
"ionic_bundler": "webpack",
"ionic_webpack": "webpack.config.ionic.js"
},
=============================================================
5-그러면 아래와 같이 사용할 수 있습니다.
@Component({
selector: 'page-login',
// templateUrl:"./login.html"
template: function(){
if(globalVariables.test==2) {
return require("./login2.html")
}
else
{
return require("./login.html")
}
}(),
})
======================================
6-require 함수와 함께 해결되지 않은 오류가 있는 경우 아래와 같이 declarations.d.ts 파일에 넣을 수 있습니다.
var require 선언: any;
기술적인 에, 요소를 구성 수 .templateUrl
다음을 사용합니다.*ngIf
올바른 템플릿을 로드하기 위해 상위 구성 요소에 있습니다.
템플릿 1을 사용하는 구성 요소:
@Component({
selector: 'template-one-component',
templateUrl: './template-one.html'
})
export class TemplateOneComponent {
title = 'This component uses one template';
}
템플릿 2를 사용하는 구성 요소:
@Component({
selector: 'template-two-component',
templateUrl: './template-two.html'
})
export class TemplateTwoComponent extends TemplateOneComponent {
}
상위 구성 요소:
@Component({
selector: 'parent-component',
template: `
<template-one-component *ngIf="useTemplateOne; else useTemplateTwo"></template-one-component>
<ng-template #useTemplateTwo>
<template-two-component></template-two-component>
<ng-template>
`
})
export class ParentComponent {
useTemplateOne: boolean;
}
언급URL : https://stackoverflow.com/questions/31692416/dynamic-template-urls-in-angular-2
'programing' 카테고리의 다른 글
Angular 2 - 이미지 URL이 유효하거나 손상되었는지 확인합니다. (0) | 2023.07.25 |
---|---|
"모듈" 패키지란 무엇입니까?json 필드는 무엇을 위해? (0) | 2023.07.25 |
Powershell에는 Aggregate/Reduce 기능이 있습니까? (0) | 2023.07.25 |
MySQL - 하위 행을 추가하거나 업데이트할 수 없습니다. (0) | 2023.07.25 |
"요청한 PHP 확장자 bcmath가 시스템에 없습니다." (0) | 2023.07.25 |