Home > front end >  Programatically Create an HTML Element On Only One Instance of a Javascript Object Property, When Mu
Programatically Create an HTML Element On Only One Instance of a Javascript Object Property, When Mu

Time:11-09

I have some JSON data that is a serious of objects inside an array that is fetched and outputted via PHP json_encode() and the javascript fetch() API. This data includes the results of a MySQL join on a many-to-many pivot linking table. Essentially it is outputting specific image board data where you can have the same image on multiple boards and, obviously, multiple boards. This all works as expected.

The Context

An example of this data is:

[
    {board_id: 428, board_name: 'tree board', image_id: 269}
    {board_id: 428, board_name: 'tree board', image_id: 292}
    {board_id: 426, board_name: 'Urban and City', image_id: 269}
    {board_id: 426, board_name: 'Urban and City', image_id: 292}
    {board_id: 426, board_name: 'Urban and City', image_id: 410}
    {board_id: 365, board_name: 'random stuff', image_id: 269}
    {board_id: 365, board_name: 'random stuff', image_id: 292}
]

Within a then() method of the JavaScript fetch() I am trying to create some button elements based on this data and append them to a parent wrapper, where only one element is created per board_id value.

An example of what this outputted HTML should look like:

<div >
    <button value="428">tree board</button>
    <button value="426">Urban and City</button>
    <button value="365">random stuff</button>
</div>

The Issue

What I can't work out is how append the element inside the wrapper div (ideally with template strings) so only one instance of each board_id value gets a button element?

In pseudo code like this:

let newButton = `
    <button value="${board_id}">${board_name}</button>
`

I appreciate I need to do this inside a loop — the array of objects is assigned to a json variable in the then() method:

let wrapper = document.querySelector('.wrapper'); // the wrapper div

json.forEach( i => {

    let boardName = i.board_name;
    let boardId = i.board_id;

    // -- somehow only only create a button on one instance of each board_id value

    // -- append the single instance of the button inside the wrapper div
})

I'm thinking when it comes to appending the templates strings I would need to utilise something like this inside the loop?

wrapper.insertAdjacentHTML('afterbegin', newButton);

Question Summary

How do I output/create a button element for only one instance of each board_id value, and then append this inside the parent wrapper?

Any help or suggestions hugely appreciated

CodePudding user response:

To ensure that buttons are captured in order create two separate arrays: one to contain existing board ids, the other to contain the buttons HTML.

Use a loop. If the board id isn't in the ids array add it, and then add in the button HTML to the buttons array. Then just join the buttons array up, and add the complete HTML string to the wrapper element.

const data=[{board_id:428,board_name:"tree board",image_id:269},{board_id:428,board_name:"tree board",image_id:292},{board_id:426,board_name:"Urban and City",image_id:269},{board_id:426,board_name:"Urban and City",image_id:292},{board_id:426,board_name:"Urban and City",image_id:410},{board_id:365,board_name:"random stuff",image_id:269},{board_id:365,board_name:"random stuff",image_id:292}];

const wrapper = document.querySelector('.wrapper');

const ids = [];
const buttons = [];

for (const { board_id, board_name } of data) {
  if (!ids.includes(board_id)) {
    ids.push(board_id);
    buttons.push(`<button value=${board_id}>${board_name}</button>`);
  }
}

wrapper.innerHTML = buttons.join('');
<div >
</div>

Additional documentation

  • Related