Динамическое создание адаптивных карточек с различным содержимым с помощью Microsoft Bot Framework

#javascript #botframework

#javascript #botframework

Вопрос:

Я пытаюсь создать адаптивную карусель карточек для моего чат-бота Azure.

У меня есть список объектов, и для каждого элемента этого списка я хочу создать новую адаптивную карточку.

Вот куда я отправляю карусель карточек:

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

И вот 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;}
  

Проблема в том, что все карточки отображают одинаковое содержимое. Количество отображаемых карточек соответствует количеству positions , но на всех карточках отображаются position.name и position.activities первого position из positions .

Вопрос: Что не так с тем, как я пытаюсь динамически создавать карточки? Как я могу успешно выполнить это?

Такое ощущение, что я упускаю что-то действительно простое, но я не смог найти причину проблемы.

Ответ №1:

Все ваши ссылки на карточки указывают на один и тот же объект, поэтому, изменяя одну из них, вы в конечном итоге меняете их все. Чтобы предотвратить такое поведение, создавайте копию карточки каждый раз, когда вы создаете новую. Вы можете использовать JSON.parse(JSON.stringify(JobCard)) для создания глубокой копии объекта JSON. Вот как должен выглядеть ваш код.

 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;
}
  

Надеюсь, это поможет!

Ответ №2:

Вместо указания JobCard в файле JSON вы также можете указать его в файле JavaScript и экспортировать функцию, которая принимает позицию в качестве аргумента и возвращает JobCard. Вот пример:

 // JobCard.js
function JobCard(position) {
  return {
    $schema: 'http://adaptivecards.io/schemas/adaptive-card.json',
    type: 'AdaptiveCard',
    version: '1.0',
    body: [
      {
        type: 'Container',
        items: [
          {
            type: 'TextBlock',
            text: 'Your Job',
            weight: 'bolder',
            size: 'medium',
          },
        ],
      },
      {
        type: 'Container',
        items: [
          {
            type: 'FactSet',
            facts: [
              {
                title: 'Activity:',
                value: position.activity,
              },
              {
                title: 'Name:',
                value: position.name,
              },
            ],
          },
        ],
      },
    ],
  }
}

module.exports = JobCard
  
 // createCards.js
const { CardFactory } = require('botbuilder')
const JobCard = require('./JobCard')

function createCards(positions) {
  return positions.map(position => CardFactory.adaptiveCard(JobCard(position)))
}

module.exports = createCards