Search code examples
javascriptbotframework

Dynamically create adaptive cards with different content using Microsoft Bot Framework


I'm trying to create an adaptative cards carousel to my Azure chatbot.

I have a list of objects and for each item of this list, I want to create a new adaptative card.

Here is where I'm sending the cards carousel:

await step.context.sendActivity({
            text: "I've found the following job positions:",
            attachments: this.createCards(positions),
            attachmentLayout: AttachmentLayoutTypes.Carousel
        });

And here is the createCards:

const JobCard = require('../../resources/jobCard.json');
createCards(positions) {
    let cards = [];         
    positions.forEach(function(position) {
        let cardJson = JobCard;
        cardJson.body[0].columns[0].items[0].text = position.name;
        cardJson.body[0].columns[0].items[1].text = position.activities;  
        let adaptativeCard = CardFactory.adaptiveCard(cardJson);
        cards.push(adaptativeCard)
    })
    return cards;}

The issue is: all the cards are displaying the same content. The number of cards being displayed is accordingly with the number of positions, but all the cards are displaying the position.name and position.activities of the first position of positions.

The question: What's is wrong with the way I'm trying to dynamically create the cards? How can I successfully accomplish this?

It feels like I'm missing something really simple here, but I couldn't find what is causing the issue.


Solution

  • All of your cards references are pointing to the same object, so when you modify one of them, you end up changing all of them. To prevent this behavior, create a copy of the card each time you make a new one. You can use JSON.parse(JSON.stringify(JobCard)) to create a deep copy of a JSON Object. Here is how your code should look.

    createCards(positions) {
        let cards = [];         
        positions.forEach(function(position) {
            let cardJson = JSON.parse(JSON.stringify(JobCard));
            cardJson.body[0].columns[0].items[0].text = position.name;
            cardJson.body[0].columns[0].items[1].text = position.activities;  
            let adaptativeCard = CardFactory.adaptiveCard(cardJson);
            cards.push(adaptativeCard)
        })
        return cards;
    }
    

    Hope this helps!