1

EDIT: This is a Web component in a static HTML file, I'm only using Angular to compile it.

I am experimenting with Angular Elements and have created a webcompoent that is a simple NgFor with an input from a JSON file.

<div *ngFor="let name of names | keyvalue" (click)="onClick(name)">
{{name.value | json}}
</div

JSON

[ 
{  
    "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"
}
]

This outputs in the browser

  { "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" }

What I want to do is access the properties in this object so when I click on one of them it updates the img src of another element with the source in the image value.

If I go back to the template and try to use {{name.value.image}} I get the error :

Property 'image' does not exist on type 'string'.

How do I get access to the image value in this object so I can use it elsewhere?

Please bear in mind that I am compiling this with Angular Elements and using it within a static html page. Thanks

Bwizard
  • 955
  • 2
  • 15
  • 36
  • 1
    your question is not clear. can you add it https://stackblitz.com/edit/stackoverflow-58672441?file=src/app/app.component.ts – Sudarshana Dayananda Nov 02 '19 at 15:35
  • @SudarshanaDayananda This is great but that is working in Angular, I am using Angular Elements to build a web Component then including it in a static html file. – Bwizard Nov 02 '19 at 15:42

3 Answers3

1

Since names is an array of objects, you do not need to use keyvalue in here.

Try like this:

<div *ngFor="let name of names" (click)="onClick(name)">
    {{name.image}}
</div>
Adrita Sharma
  • 21,581
  • 10
  • 69
  • 79
  • Thanks but I still get the compilation error: Property 'image' does not exist on type 'string'. – Bwizard Nov 02 '19 at 15:39
0

I think you need something like this:

component.ts:

import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
public names = [ 
{  
    "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"
}
];


public imgSrc = '';

public setSource(name) {
  this.imgSrc = name.image;
}
}

and the HTML:

<div *ngFor="let name of names" (click)="setSource(name)">
{{name.image | json}}
</div>

<img [src]="imgSrc" >

brandt.codes
  • 923
  • 2
  • 9
  • 19
  • Thanks. That is indeed how it would work if it was not a Web Component. Please see my answer for my explanation. Thanks – Bwizard Nov 03 '19 at 11:47
0

OK so I realised what I was doing wrong. Because it is a Web Component and any string or object can be passed via the html property I can't know what the property names will be when compiling the component in angular. So names.anything will cause an error when compiling.

The solution was to emit the whole object via the @Output, add an eventlistener in the html script then select the property from the event object. Hopefully the below will make it clear what I was trying to achieve and why I was experiencing problems. <name-list/> is the name of my webcomponent and behind the scenes looks like <name-list names="{object}"/>

<name-list />
<img></img>
<script src="elementCommunicationWithDom.js"></script>// this is the compiled Angular elements file
<script>
    init();
    function loadJSON(callback) {   //needed to access local JSON file

        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);
            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');
    element.addEventListener("onSelectItem", (event) => { //gets the output of @Output which is onSelectItem
        img.src = event.detail.image;
        console.log(event.detail.image)
    })

</script>
Bwizard
  • 955
  • 2
  • 15
  • 36