AdaptiveCards: [Javascript][Application (Author) Rendering] [Don't delete fields where the template doesn't resolve]

Platform

What platform is your issue or question related to? (Delete other platforms).

  • JavaScript

Author or host

Author – sending cards to Webex Teams.

Version of SDK

adaptivecards-templating@0.1.1-alpha.0

Details

I’m using the JS Template SDK in my app to populate template cards with data before posting them (to Webex Teams in my case). I’ve noticed that if I attempt to expand a template that does not define all of the “templatized” fields in my design the fields that are not populated are deleted.

As an alternative, perhaps the fields could be left unchanged? In my case I actually do a second pass, and would like the fields that were not populated in the first pass to still remain so they can be exposed in the second pass.

As an example, let’s define a card with two templateized fields, but create a context that only satisfies one of them:

let ACData = require("adaptivecards-templating");
let cardDesign = {...
  body [
   {
      "type": "TextBlock",
      "id": "{id}",
       "text": "{text}"
    }
  ]...
};
let  template = new ACData.Template(cardDesign);
let context = new ACData.EvaluationContext();
      context.$root = {
         id: "1234"
      };
let card = template.expand(context);

The resulting card will be:

{...
  body [
   {
      "type": "TextBlock",
      "id": "1234"
    }
  ]...
};

Note the text field is eliminated (making this invalid according to the schema)

An alternative would be to leave it unchanged:

{...
  body [
   {
      "type": "TextBlock",
      "id": "1234",
      "text": "{text}"
    }
  ]...
};

In this case if the card is rendered, it is quickly obvious what the problem is. If the application performs multi-pass templating (as mine attempted to do), there are additional opportunities to expand the template before the render request.

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Comments: 23 (20 by maintainers)

Most upvoted comments

@nesalang I think we might be talking past each other. But let me try to be more precise.

What you call an “invalid” expression is not necessarily “invalid.”

Take this data object:

[
  {
    "firstName": "David",
    "lastName": "Claux",
    "shortBio": "David Claux is a PM at Microsoft"
  },
  {
    "firstName": "Matt",
    "lastName": "Hidinger"
  }
]

So essentially an array with two objects; the "shortBio" property is not required, and for Matt is not present (and is therefore undefined).

Now consider this template:

{
  "type": "AdaptiveCard",
  "body": [
    {
      "type": "TextBlock",
      "text": "{shortBio}"
    }
  ]
}
  • The expression "{shortBio}" is valid. Sometimes, shortBio will be specified in the data object, sometimes it won’t
  • Thus it needs to evaluate to something
  • For Matt, that something is undefined
  • And because of that, template expansion generates the following card:
{
  "type": "AdaptiveCard",
  "body": [
    {
      "type": "TextBlock",
      "text": "David Claux is a PM at Microsoft"
    },
    {
      "type": "TextBlock"
    }
  ]
}

When that card is fed to the renderer, the second TextBlock is dropped because it doesn’t have a text property.

@jpjpjp wants the generated card to look like this:

{
  "type": "AdaptiveCard",
  "body": [
    {
      "type": "TextBlock",
      "text": "David Claux is a PM at Microsoft"
    },
    {
      "type": "TextBlock",
      "text": "{shortBio}"
    }
  ]
}

So essentially he wants the template engine to have an option to leave the expression string as is in the generated payload in the case it evaluates to undefined.

No matter how many opportunities, templating always happens before rendering, and the problem is it generates a TextBlock with an unspecified text 😊