首页 > 解决方案 > 在导出的 Angular Elements Web 组件上设置事件监听器

问题描述

编辑:这是一个使用 Angular Elements 从 Angular 导出的 Web 组件,不是传统的 Angular

我正在试验 Angular Elements 并创建了一个加载下面 JSON 文件的 NgFor 组件。

[ 
{  
    "id":1,
    "name": "star 1",
    "image":"https://picsum.photos/id/1059/400/400",
    "text":"Text about star 1"
},
{  
    "id":2,
    "name": "star 2",
    "image":"https://picsum.photos/id/1060/400/400",
    "text":"Text about star 2"
},
{  
    "id":3,
    "name": "star 3",
    "image":"https://picsum.photos/id/1061/400/400",
    "text":"Text about star 3"
},
{  
    "id":4,
    "name": "star 4",
    "image":"https://picsum.photos/id/1062/400/400",
    "text":"Text about star 4"
},
{  
    "id":5,
    "name": "star 5",
    "image":"https://picsum.photos/id/1063/400/400",
    "text":"Text about star 5"
},
{  
    "id":6,
    "name": "star 6",
    "image":"https://picsum.photos/id/1064/400/400",
    "text":"Text about star 6"
},
{  
    "id":7,
    "name": "star 7",
    "image":"https://picsum.photos/id/1065/400/400",
    "text":"Text about star 7"
},
{  
    "id":8,
    "name": "star 8",
    "image":"https://picsum.photos/id/1066/400/400",
    "text":"Text about star 8"
},
{  
    "id":9,
    "name": "star 9",
    "image":"https://picsum.photos/id/1067/400/400",
    "text":"Text about star 9"
},
{  
    "id":10,
    "name": "star 10",
    "image":"https://picsum.photos/id/1068/400/400",
    "text":"Text about star 10"
}
]

这会在浏览器中呈现一个列表

Star1
Star2
Star3
.
.
etc

这些元素上有一个 onClick 函数,它通过 @Output 属性发出对象。

然后,我在 HTML 中的脚本标记中有一个 eventListener,它侦听此发出并使用相关图像更新 img 标记中的 src 属性。

我的问题是;我想创建另一个内置了这个 eventListener 的 WebComponent,这样我就可以将第二个组件添加到 HTML 中,然后它们将相互通信,而无需我直接在脚本标签中编写 eventListener。我当前的代码。

<name-list />
<img-comp />
<img></img>  //not needed if <img-comp> can receive the emitted data
<script src="elementCommunicationWithDom.js"></script>
<script>
    init();
    function loadJSON(callback) {

        var xobj = new XMLHttpRequest();
        xobj.overrideMimeType("application/json");
        xobj.open('GET', 'data.json', true);
        xobj.onreadystatechange = function () {
            if (xobj.readyState == 4 && xobj.status == "200") {
                callback(xobj.responseText);
            }
        };
        xobj.send(null);
    }

    function init() {
        loadJSON(function (response) {
            var obj = JSON.parse(response);
            console.log(obj);
            let element = document.querySelector('name-list');
            element.names = obj; //set the html property names created in @input in Angular to the object
        });
    }

    let element = document.querySelector('name-list');
    let img = document.querySelector('img');
    // I want to do the below directly within the <img-comp> component
    element.addEventListener("onSelectItem", (event) => { //gets the output of @Output which is onSelectItem
        img.src = event.detail.image;
        console.log(event.detail.image)
    })

</script>

回到我的 Angular 组件中,因为<img-comp>我有以下内容

模板

<img [src]="imgsrc" />

零件

 @Component({
  selector: 'app-img-comp',
  templateUrl: './img-comp.component.html',
  styleUrls: ['./img-comp.component.css']
})
export class ImgCompComponent implements OnInit {

  @Input() imgsrc: string;


  //This below is incorrect and is what I need I think to make this work
 @HostListener('onSelectItem', ['$event'])
  OnStarClicked(event) {
  this.imgsrc = event.detail.image;
  console.log(event.detail.image);
 }  

如何获取 @Hostlistener 属性以正确添加 html 脚本标记中的等效 eventListener?

https://stackblitz.com/edit/angular-ej7fnv

标签: javascriptangularweb-componentangular-elements

解决方案


我不确定你的 comonnets 的结构是什么样的,但你必须记住:

EventEmitters !== DOM 事件

与 DOM 事件不同,Angular 自定义事件不会冒泡。这意味着您只能在父级别收听组件的事件。

您可以创建本机 DOM 事件,如下所示:

constructor(private el: ElementRef) { }

onClick(star) {
  this.el.nativeElement
    .dispatchEvent(new CustomEvent('onSelectItem', {
      detail: star,
      bubbles: true
    }));
}

我希望它有帮助。


推荐阅读