Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angular/31.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Angular 如何在传单标记内生成角度4分量';什么是弹出窗口?_Angular_Leaflet_Web Component - Fatal编程技术网

Angular 如何在传单标记内生成角度4分量';什么是弹出窗口?

Angular 如何在传单标记内生成角度4分量';什么是弹出窗口?,angular,leaflet,web-component,Angular,Leaflet,Web Component,我一直是Angular 1.x的长期用户,现在我正在使用Angular 4制作一个新的应用程序。我仍然没有掌握大部分的概念,但我终于有了一些非常好的东西。然而,我遇到了一个问题,我需要在使用传单的标记弹出窗口中显示一个角度为4的组件(尽管在1.x中我刚刚使用了指令) 现在,在Angular 1.x中,我可以对一个模板使用$compile,该模板中有指令(`{{text}}}`)和按钮等,它可以工作,但是Angular 4与它的AoT完全不同,在运行时编译似乎非常困难,而且没有简单的解决方案 我问

我一直是Angular 1.x的长期用户,现在我正在使用Angular 4制作一个新的应用程序。我仍然没有掌握大部分的概念,但我终于有了一些非常好的东西。然而,我遇到了一个问题,我需要在使用传单的标记弹出窗口中显示一个角度为4的组件(尽管在1.x中我刚刚使用了指令)

现在,在Angular 1.x中,我可以对一个模板使用$compile,该模板中有指令(
`{{text}}}`
)和按钮等,它可以工作,但是Angular 4与它的AoT完全不同,在运行时编译似乎非常困难,而且没有简单的解决方案

我问了一个问题,作者说我可以使用指令。我不确定这是否是正确的方法,甚至不确定如何将我自己的代码与他提出的解决方案混合使用。。。所以我做了一个基于npm的小项目,Angular 4和传单已经准备好了,以防你们知道如何帮助我或者想尝试一下(我非常感谢!)。我已经为此绞尽脑汁一个星期了,我真的厌倦了尝试许多没有成功的替代方案:(

以下是我在GitHub中的回购链接:

其思想是在标记中生成PopupComponent(或任何类似的东西),代码可以在src/app/services/map.service.ts第38行找到

提前感谢!:)

编辑

我设法解决了:)详细信息请参见标记的答案,或此差异。有一些注意事项,Angular 4和传单的程序有点不同,不需要太多更改:


我还为此解决方案制作了一个定制的编译服务,并将其解释和上传到同一个GitHub repo。谢谢@yurzui!:)

好吧,多亏@ghybs的建议,我再次尝试了这个链接,并设法解决了这个问题:D.传单与谷歌地图有点不同(它也比较短),建议的解决方案可能会更小,更容易理解,所以这里是我使用传单的版本

基本上,您需要将弹出组件放在主应用程序模块的
entryComponents
字段中。关键在于
m.onclick()
,在那里,我们创建一个组件,在
div
中呈现它,然后将
div
的内容传递给传单弹出容器元素。有点棘手,但它是有效的

我花了一些时间,将这个解决方案转换为Angular 4的新$compile。查看详细信息。谢谢@yurzui!:)

这是核心代码。。。其他内容(css、webpack等)与OP在同一个repo中,简化为几个文件:但您只需要以下示例即可:

import 'leaflet';
import './main.scss';
import "reflect-metadata";
import "zone.js/dist/zone";
import "zone.js/dist/long-stack-trace-zone";
import { BrowserModule } from "@angular/platform-browser";
import { platformBrowserDynamic } from "@angular/platform-browser-dynamic";
import { Component, NgModule, ComponentRef, Injector, ApplicationRef, ComponentFactoryResolver, Injectable, NgZone } from "@angular/core";

// ###########################################
// App component
// ###########################################
@Component({
    selector: "app",
    template: `<section class="app"><map></map></section>`
})
class AppComponent { }

// ###########################################
// Popup component
// ###########################################
@Component({
    selector: "popup",
    template: `<section class="popup">Popup Component! :D {{ param }}</section>`
})
class PopupComponent { }

// ###########################################
// Leaflet map service
// ###########################################
@Injectable()
class MapService {

    map: any;
    baseMaps: any;
    markersLayer: any;

    public injector: Injector;
    public appRef: ApplicationRef;
    public resolver: ComponentFactoryResolver;
    public compRef: any;
    public component: any;

    counter: number;

    init(selector) {
        this.baseMaps = {
            CartoDB: L.tileLayer("http://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png", {
                attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> &copy; <a href="http://cartodb.com/attributions">CartoDB</a>'
            })
        };
        L.Icon.Default.imagePath = '.';
        L.Icon.Default.mergeOptions({
            iconUrl: require('leaflet/dist/images/marker-icon.png'),
            shadowUrl: require('leaflet/dist/images/marker-shadow.png')
        });
        this.map = L.map(selector);
        this.baseMaps.CartoDB.addTo(this.map);
        this.map.setView([51.505, -0.09], 13);

        this.markersLayer = new L.FeatureGroup(null);
        this.markersLayer.clearLayers();
        this.markersLayer.addTo(this.map);
    }

    addMarker() {
        var m = L.marker([51.510, -0.09]);
        m.bindTooltip('Angular 4 marker (PopupComponent)');
        m.bindPopup(null);
        m.on('click', (e) => {
            if (this.compRef) this.compRef.destroy();
            const compFactory = this.resolver.resolveComponentFactory(this.component);
            this.compRef = compFactory.create(this.injector);

            this.compRef.instance.param = 0;
            setInterval(() => this.compRef.instance.param++, 1000);

            this.appRef.attachView(this.compRef.hostView);
            this.compRef.onDestroy(() => {
                this.appRef.detachView(this.compRef.hostView);
            });
            let div = document.createElement('div');
            div.appendChild(this.compRef.location.nativeElement);
            m.setPopupContent(div);
        });
        this.markersLayer.addLayer(m);
        return m;
    }
}

// ###########################################
// Map component. These imports must be made
// here, they can't be in a service as they
// seem to depend on being loaded inside a
// component.
// ###########################################
@Component({
    selector: "map",
    template: `<section class="map"><div id="map"></div></section>`,
})
class MapComponent {

    marker: any;
    compRef: ComponentRef<PopupComponent>;

    constructor(
        private mapService: MapService,
        private injector: Injector,
        private appRef: ApplicationRef,
        private resolver: ComponentFactoryResolver
    ) { }

    ngOnInit() {
        this.mapService.init('map');
        this.mapService.component = PopupComponent;
        this.mapService.appRef = this.appRef;
        this.mapService.compRef = this.compRef;
        this.mapService.injector = this.injector;
        this.mapService.resolver = this.resolver;
        this.marker = this.mapService.addMarker();
    }
}

// ###########################################
// Main module
// ###########################################
@NgModule({
    imports: [
        BrowserModule
    ],
    providers: [
        MapService
    ],
    declarations: [
        AppComponent,
        MapComponent,
        PopupComponent
    ],
    entryComponents: [
        PopupComponent
    ],
    bootstrap: [AppComponent]
})
class AppModule { }

platformBrowserDynamic().bootstrapModule(AppModule);
导入“传单”;
导入“/main.scss”;
导入“反映元数据”;
导入“zone.js/dist/zone”;
导入“zone.js/dist/long stack trace zone”;
从“@angular/platform browser”导入{BrowserModule}”;
从“@angular/platformBrowserDynamic”导入{platformBrowserDynamic}”;
从“@angular/core”导入{Component,NgModule,ComponentRef,Injector,ApplicationRef,ComponentFactoryResolver,Injectable,NgZone};
// ###########################################
//应用程序组件
// ###########################################
@组成部分({
选择器:“应用程序”,
模板:``
})
类AppComponent{}
// ###########################################
//弹出组件
// ###########################################
@组成部分({
选择器:“弹出”,
模板:`弹出组件!:D{{param}`
})
类PopupComponent{}
// ###########################################
//单张地图服务
// ###########################################
@可注射()
类映射服务{
地图:任何;
基本地图:任何;
标记层:任何;
公共注射器:注射器;
公共appRef:ApplicationRef;
公共解析器:ComponentFactoryResolver;
公共压缩机:任何;
公共部分:任何;
柜台:号码;
初始化(选择器){
此值为0.baseMaps={
CartoDB:L.tileLayer(“http://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png”{
属性:“©;©;”
})
};
L.Icon.Default.imagePath=';
L.Icon.Default.mergeOptions({
iconUrl:require('传单/dist/images/marker-icon.png'),
shadowUrl:require('传单/dist/images/marker shadow.png'))
});
this.map=L.map(选择器);
this.baseMaps.CartoDB.addTo(this.map);
这个.map.setView([51.505,-0.09],13);
this.markersLayer=新的L.FeatureGroup(null);
this.markersLayer.clearLayers();
this.markersLayer.addTo(this.map);
}
addMarker(){
var m=L.marker([51.510,-0.09]);
m、 bindTooltip(“角度4标记(PopupComponent)”;
m、 bindPopup(空);
m、 在('点击',(e)=>{
如果(this.compRef)this.compRef.destroy();
const compFactory=this.resolver.resolveComponentFactory(this.component);
this.compRef=compFactory.create(this.injector);
this.compRef.instance.param=0;
setInterval(()=>this.compRef.instance.param++,1000);
this.appRef.attachView(this.compRef.hostView);
this.compRef.ondestory(()=>{
this.appRef.detachView(this.compRef.hostView);
});
设div=document.createElement('div');
div.appendChild(this.compRef.location.nativeElement);
m、 setPopupContent(div);
});
这个.markersLayer.addLayer(m);
返回m;
}
}
// ###########################################
//映射组件。这些进口商品必须进口
//在这里,他们不可能像他们一样在服役
//似乎依赖于被装入一个
//组成部分。
// ###########################################
@组成部分({
选择器:“地图”,
模板:``,
})
类映射组件{
标记:任何;
ComponentRef:ComponentRef;
建造师(
私人地图服务:
   entryComponents: [
      ...,
      MycustomPopupComponent
   ],
constructor(
    ...
    private componentFactoryResolver: ComponentFactoryResolver,
    private injector: Injector
) {
private createCustomPopup() { 
    const factory = this.componentFactoryResolver.resolveComponentFactory(MycustomPopupComponent);
    const component = factory.create(this.injector);

    //Set the component inputs manually 
    component.instance.someinput1 = "example";
    component.instance.someinput2 = "example";

    //Subscribe to the components outputs manually (if any)        
    component.instance.someoutput.subscribe(() => console.log("output handler fired"));

    //Manually invoke change detection, automatic wont work, but this is Ok if the component doesn't change
    component.changeDetectorRef.detectChanges();

    return component.location.nativeElement;
}
const marker = L.marker([latitude, longitude]).addTo(this.map);
marker.bindPopup(() => this.createCustomPopup()).openPopup();