Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🤖 Templating for JavaScript and .NET now available! #2448

Closed
matthidinger opened this issue Feb 22, 2019 · 36 comments
Closed

🤖 Templating for JavaScript and .NET now available! #2448

matthidinger opened this issue Feb 22, 2019 · 36 comments
Labels
Area-Templating no-recent-activity Platform-.NET Platform-JavaScript Bugs or features related to the JavaScript renderer

Comments

@matthidinger
Copy link
Member

matthidinger commented Feb 22, 2019

We're excited to announce the v1.0 release of Adaptive Card Templating for JavaScript and .NET, which enables the separation of data from layout in your Adaptive Cards.

Breaking changes as of May 2020

  1. The binding syntax changed from {...} to ${...}.
    • For Example: "text": "Hello {name}" becomes "text": "Hello ${name}"
  2. The JavaScript API no longer contains an EvaluationContext object. Simply pass your data to the expand function. Please see the SDK page for full details.
  3. The .NET API was redesigned to more closely match the JavaScript API. Please see the SDK page for full details.

Get started today!

Templating is a standalone library, which means you can start using it today with any Adaptive Card host, like Teams, Outlook, or your own apps.

How can templating help you?

Templating enables the separation of data from the layout in an Adaptive Card.

It helps design a card once, and then populate it with real data

Today it's impossible to create a card using the Adaptive Card Designer and use that JSON to populate the payload with dynamic content. In order to achieve this you must write custom code to build a JSON string, or use the Object Model SDKs to build an OM representing your card and serialize it to JSON. In either case the Designer is a one-time one-way operation and doesn't make it easy to tweak the card design later once you've converted it to code.

It makes transmissions over the wire smaller

Imagine a world where a template and data can be combined directly on the client. This means if you use the same template multiple times, or want to update it with new data, you just need to send new data to the device and it can re-use the same template over and over.

It helps you create a great looking card from just the data you provide

We think Adaptive Cards are great, but what if you didn't have to write an Adaptive Card for everything you want to display to a user? With a template service (described below) we can create a world where everyone can contribute, discover, and share templates over any type of data.

Share within your own projects, your organization, or with the entire internet.

AI and other services could improve user experiences

By separating data from content it opens a door for AI and other services to "reason" over the data in the cards we see and enhance user productivity or help us find things.

What is Adaptive Cards Templating?

It's comprised of 3 major components:

  1. The Template Language is the syntax used for authoring a template. The Designer even lets you preview your templates at design time by including "sample data".
  2. The Templating SDK's will exist on all supported Adaptive Card platforms. These SDKs allow you to populate a template with real data, on the back-end or directly on the client.
  3. The Template Service is a proof-of-concept service that allows anyone to find, contribute to, and share a set of well-known templates.

Template Language

The template language is the syntax used to author an Adaptive Card template.

Follow along with the example below by opening up a new tab to

https://adaptivecards.io/designer

Click the Preview Mode button to toggle between design-mode and preview-mode.

Designer screenshot

The newly updated Designer adds support for authoring templates and providing Sample Data to preview the card at design-time.

Paste the example below into the Card Payload Editor pane:

EmployeeCardTemplate.json

{
    "type": "AdaptiveCard",
    "version": "1.0",
    "body": [
        {
            "type": "ColumnSet",
            "style": "accent",
            "bleed": true,
            "columns": [
                {
                    "type": "Column",
                    "width": "auto",
                    "items": [
                        {
                            "type": "Image",
                            "url": "${photo}",
                            "altText": "Profile picture",
                            "size": "Small",
                            "style": "Person"
                        }
                    ]
                },
                {
                    "type": "Column",
                    "width": "stretch",
                    "items": [
                        {
                            "type": "TextBlock",
                            "text": "Hi ${name}!",
                            "size": "Medium"
                        },
                        {
                            "type": "TextBlock",
                            "text": "Here's a bit about your org...",
                            "spacing": "None"
                        }
                    ]
                }
            ]
        },
        {
            "type": "TextBlock",
            "text": "Your manager is: **${manager.name}**"
        },
        {
            "type": "TextBlock",
            "text": "Your peers are:"
        },
        {
            "type": "FactSet",
            "facts": [
                {
                    "$data": "${peers}",
                    "title": "${name}",
                    "value": "${title}"
                }
            ]
        }
    ]
}

Then paste the JSON data below into the Sample Data Editor.

Sample Data helps you see exactly how your card will appear at runtime when passed actual data.

EmployeeData

{
    "name": "Matt",
    "photo": "https://pbs.twimg.com/profile_images/3647943215/d7f12830b3c17a5a9e4afcc370e3a37e_400x400.jpeg",
    "manager": {
        "name": "Thomas",
        "title": "PM Lead"
    },
    "peers": [
        {
            "name": "Lei",
            "title": "Sr Program Manager"
        },
        {
            "name": "Andrew",
            "title": "Program Manager II"
        },
        {
            "name": "Mary Anne",
            "title": "Program Manager"
        }
    ]
}

Click the Preview Mode button. You should see the card render according to the sample data provided above. Feel free to make tweaks to the sample data and watch the card update in realtime.

Congratulations, you just authored your first Adaptive Card Template! Next let's learn how to populate the template with real data.

Learn more about the template language

SDK support

The Templating SDKs make it possible to populate a template with real-data.

NOTE: At this time templating is targeted primarily for "backend" platforms (.NET and NodeJS). Over time we will release templating SDKs for all remaining Adaptive Cards platform, like iOS, Android, UWP, etc.

Platform Package Install Documentation
JavaScript npm install npm install adaptivecards-templating Documentation
.NET Nuget install dotnet add package AdaptiveCards.Templating Documentation

JavaScript Example

The JavaScript below shows the general pattern that will be used to populate a template with data.

var template = new ACData.Template({ 
    // EmployeeCardTemplate goes here
});

var card = template.expand({
    $root: {
        // Your data goes here
    }
});
// Now you have an AdaptiveCard ready to render!

Learn more about the templating SDKs

Template Service

The Adaptive Cards Template Service is a proof-of-concept service that allows anyone to find, contribute to, and share a set of well-known templates.

It's useful if you want to display some data but don't want to bother writing a custom Adaptive Card for it.

The API to get a template is straight-forward enough, but the service actually offers much more, including the ability to analyze your data and find a template that might work for you.

HTTP GET https://templates.adaptivecards.io/graph.microsoft.com/Profile.json

All templates are flat JSON files stored in a GitHub repo so anyone can contribute to them like any other open source code.

Learn more about the card template Service

What's next and sending feedback

Templating and the separation of presentation from data takes us a whole lot closer toward our mission: "an ecosystem standardized content exchange between apps and services". We've got plenty to deliver in this area, so stay tuned and let us know how it's working for you on GitHub!

@matthidinger matthidinger pinned this issue Feb 22, 2019
@matthidinger matthidinger changed the title [Preview] Data Binding in Adaptive Cards "2.0" 🤖 [Preview] Data Binding in Adaptive Cards "2.0" Feb 22, 2019
@v-kydela
Copy link

@matthidinger - This is all very excellent! I'm on the Bot Framework support team and I use Adaptive Cards frequently and I'm always excited to hear new things about Adaptive Cards.

Since you asked, I do have some feedback. It seems to me like there are two ways to implement these features and I'm not sure what path you're taking.

  1. This could be a new version of the Adaptive Cards schema which would mean all this new syntax would be included in the payload being sent to whatever channel is meant to render the card.
  2. This could just be a new version of the Adaptive Cards packages, meaning a card would be converted from this new syntax into the old syntax before being sent to the channel.

Since this is being called Adaptive Cards "2.0" I'm a little confused. The name 2.0 implies that it's a new schema like Adaptive Cards 1.1. But it's in quotes, which might imply that you don't mean that.

It seems to me like this whole data binding feature could very easily be implemented using option 2, and my feedback is that it should be. That's not to say I don't think there should be any new versions of the schema. It's just that from my point of view, if you can implement a feature without requiring a new schema then it's very logical to do so.

Channels have been slow to implement support of Adaptive Cards 1.1, so we might expect the same regarding Adaptive Cards 2.0. If we can implement this new feature such that we're not counting on channels to implement support of a new Adaptive Cards schema, we'll get all the benefits of the new feature while still being able to reach as many channels as possible. The way to do this is of course to have cards containing the data binding syntax get converted into "classic" Adaptive Cards syntax on the bot side, before the card is sent to the channel. That way the channel wouldn't need to be responsible for interpreting the syntax.

@andrewleader
Copy link
Contributor

@v-kydela that definitely could be possible! From the Bot Framework side, you could parse the new template/data card using the new Adaptive Card library, and then call a "populate" method to populate the data into the template, generating a fully self-contained Adaptive Card, which you then can send to all the channels.

Our current thoughts is that the templating/data binding will happen BEFORE rendering, so you can apply the templating ahead of time. Authors could even choose to apply the templating before they even send Bot Framework the card.

Good to know that you might use this feature in that way! Thanks!

@andrewleader andrewleader changed the title 🤖 [Preview] Data Binding in Adaptive Cards "2.0" 🤖 [Preview] Templating language, a.k.a. Adaptive Cards "2.0" May 27, 2019
@AndreMantas
Copy link

When will we be able to install a pre-release via nugget? We are waiting for this feature for so long :)

@andrewleader
Copy link
Contributor

Hey @AndreMantas, you're looking for a .NET version? We have a JavaScript version on NPM: https://www.npmjs.com/package/adaptivecards-templating

Let us know if you want the .NET version on NuGet and we probably could get around to packaging up the current alpha! Also let us know what version of .NET you need it on (.NET standard 1.3, 2.0, or .NET PCL, etc)

@AndreMantas
Copy link

Hi. Yes I'm looking for a .NET Core version.
Currently when creating new bots via the microsoft template I believe projects are set to .NET Core 2.1, but I usually switch to 2.2.

@andrewleader
Copy link
Contributor

@AndreMantas we've got a PR in-progress (#3239) for a .NET Standard 2.0 library, you could compile from that source, or here's a pre-compiled NuGet from OneDrive that you could copy locally and consume until we get it merged and published to NuGet.org!

See the readme for a quick explanation on how to use the .NET library!

@rvinothrajendran
Copy link

rvinothrajendran commented Sep 23, 2019

@matthidinger,@andrewleader where I can download the new AdaptiveCard.FromJson API supporting package for C#

@matthidinger
Copy link
Member Author

@paulcam206 is working on this as we speak, hopefully not much longer

@matthidinger
Copy link
Member Author

matthidinger commented Oct 8, 2019

@rvinothrajendran please see the package here: https://www.nuget.org/packages/AdaptiveCards.Templating

Note that the API has changed since this was posted.

var transformer = new AdaptiveTransformer();
var cardJson = transformer.Transform(templateJson, dataJson);

Please give it a shot and let us know how it works for you! Also, I will be updating the main issue, but official templating docs have been posted here: https://docs.microsoft.com/en-us/adaptive-cards/templating/

@rvinothrajendran
Copy link

@matthidinger transformer.Transform() API is working fine.
Waiting for AdaptiveCards.FromJson API in C# :)

@ThomasPe
Copy link

seems to be working fine for me as well.
the binding does not seem to work when the property name has a number in it, so Location1 & Location2 failed for me while LocationX & LocationY work fine. Not sure if that's a known issue.

@matthidinger
Copy link
Member Author

Hi @ThomasPe, that's an interesting topic we're evaluating right now: type coercion. Hopefully we'll have that up for review soon, but if you were able to share more about your template payload, data, and your opinion on the most reasonable expected behavior it would be great information for us as we evaluate proposals.

@zjrunner
Copy link
Member

zjrunner commented Nov 22, 2019

@matthidinger , what is the relation to type coercion? I hit the same thing @ThomasPe saw. Adding some examples to make sure we're talking about the same thing.

This works fine:

var output = transformer.Transform("{\"hi\":\"{my.data}\"}", "{\"my\":{\"data\":\"foo\"}}");

This doesn't find the match because of the number, and leaves the {my.dat1a} in the transform result:

var output = transformer.Transform("{\"hi\":\"{my.dat1a}\"}", "{\"my\":{\"dat1a\":\"foo\"}}");

I was having trouble finding the C# code in GitHub when I saw the linked PR is still pending merge - and it is pretty lightweight and mostly runs the nodejs code which is in master. I'm rusty on JS but I think we're talking about the definition of identifier in the parse code which may be overly limiting not allowing digits:

{ tokenType: "identifier", regEx: /^[$a-z_]+/i },

@v-kydela
Copy link

Yeah that looks like bad RegEx to detect an identifier. But why does it even need RegEx to detect an identifier? Whatever is after the dot is automatically an identifier, right?

@ghost ghost added the no-recent-activity label Dec 13, 2019
@ghost
Copy link

ghost commented Dec 13, 2019

This issue has been automatically marked as stale because it has not had any activity for 5 days.

@jbeek11
Copy link

jbeek11 commented Dec 19, 2019

LS,
any update on when this might be moving from preview to general availability?
Best regards,
Joris.

@matthidinger
Copy link
Member Author

Hi @jbeek11, we have no dates yet but we're making progress :) Is there anything preventing you from using the preview that we can help with?

@jbeek11
Copy link

jbeek11 commented Dec 23, 2019 via email

@shalinijoshi19 shalinijoshi19 changed the title 🤖 [Preview] Templating language, a.k.a. Adaptive Cards "2.0" 🤖 [Preview] Templating language Package Jan 28, 2020
@amitvig22
Copy link

@matthidinger transformer.Transform() API is working fine.
Waiting for AdaptiveCards.FromJson API in C# :)

If there is an update on this please let us know :) we would like to move to an official nuget for the FromJson calls as well.

@grahamehorner
Copy link

@jbeek11 can you share information with regards your issue around the layering that you UX/frontend developer has/had; as I'd like to avoid any possible issue with our UX/frontend developers prior to going to far into adaptive card service developments. thanks in advance of any information you provide

@jbeek11
Copy link

jbeek11 commented Feb 21, 2020

@jbeek11 can you share information with regards your issue around the layering that you UX/frontend developer has

I've not mentioned an issue with 'layering', not sure what you mean by that. Our problem is that, when using Adaptive Cards in its current setup there is not full control over layout and UX in the frontend. E.g. you are limited to certain letter sizes, which you have to 'translate' into what you would like in the frontend. This gives only very limited flexibility as far as layout and UX is concerned. For us this was not the way to go, especially since we are only beginning and still have the option to go a different, more suitable route.

@v-kydela
Copy link

@jbeek11 - The Adaptive Card schema defines 5 different font sizes which each Adaptive Card renderer is able to define actual sizes for. Are you saying you need your cards to have more than 5 different font sizes?

@rbanate
Copy link

rbanate commented Mar 10, 2020

@matthidinger - I noticed that data is not being rendered on azure healthbot web chat too though I can see it working properly via the designer https://adaptivecards.io/designer/

@NxP4Code
Copy link

It is possible to have dynamic number of rows? e.g. in the Expense report template is fixed for 3 rows, is it possible to have one template row and expand it based on input array of rows?

@matthidinger
Copy link
Member Author

@NxP4Code
Copy link

@matthidinger , It kind of helps only when you know exact rows before building template. E.g. https://adaptivecards.io/samples/ExpenseReport.html , in here you need to know before creating template there are 3 rows in dataset, If I am planning to store static template file and than generate complete json based on incoming data.

In real-life its difficult to fix number of rows in template, lets say I am sending expense report card in my chat bot, all expense report will have different number of rows. So fixing 3 rows in static templating file and using data array of 3 rows is not going to be helpful. I am trying to find a way to have template to define row 1 row (1 json block in template )and expand that 1 row based on data array size. If I get 5 rows I will see template repeated 5 times.

Am I missing something big here??

@matthidinger
Copy link
Member Author

@NxP4Code that should work no problem, just set the "$data" property to an array and that adaptive card element will be repeated for each object in the array. If you can send your example card and data format with private information removed I can try to help more specifically

@NxP4Code
Copy link

@matthidinger , Thanks for your offer and support. I will try to play with it, I got the core data ready working on creating template. If I have any challenge I will post it here.

@NxP4Code that should work no problem, just set the "$data" property to an array and that adaptive card element will be repeated for each object in the array. If you can send your example card and data format with private information removed I can try to help more specifically

@NxP4Code
Copy link

@matthidinger

Is it possible to update the expense report template to use templating and data binding at appropriate places in a designer? It seems the Data context is not set and editing sample data doesn't change anything on the card. It seems the card is pretty much static.

image

@dclaux
Copy link
Member

dclaux commented Apr 14, 2020

@NxP4Code an update to the designer is coming - no ETA, but we're getting there. You can see a preview of it at https://vnext.adaptivecards.io/designer

@NxP4Code
Copy link

I got this working in the current version. what is are the enhancements in the new version?

@NxP4Code an update to the designer is coming - no ETA, but we're getting there. You can see a preview of it at https://vnext.adaptivecards.io/designer

The issue was the data array needs to be explicitly called with root context. e.g. {$root.arrayofObjectorArray}
adaptivecard

Also, I noticed that the data structure panel was not getting updated with sample data. But that is not a major issue.

@dclaux
Copy link
Member

dclaux commented Apr 14, 2020

The new designer has an updated sample picker and enhanced data binding support. The Data Structure pane is also gone.

If you're successful with the current designer no need to look into the new one for now.

@matthidinger matthidinger changed the title 🤖 [Preview] Templating language Package [May 2020] Templating Release Candidate available! May 18, 2020
@matthidinger matthidinger changed the title [May 2020] Templating Release Candidate available! 🤖 Templating Release Candidate now available! May 18, 2020
@shalinijoshi19
Copy link
Member

@matthidinger reminder to update + close this issue out post RTM push today!

@shalinijoshi19 shalinijoshi19 added AdaptiveCards v20.06 Platform-.NET Platform-JavaScript Bugs or features related to the JavaScript renderer labels Jul 6, 2020
@matthidinger matthidinger changed the title 🤖 Templating Release Candidate now available! 🤖 Templating for JavaScript and .NET now available! Jul 7, 2020
@pragadeeshk pragadeeshk unpinned this issue Jul 16, 2020
@mohitborse
Copy link

Hi Team,

I'm trying to integrate the Adaptive card designer with the Angular application. I make a one-live solution for it but in that, I'm facing one problem I'm not able to load monaco editor in that.

So anyone can provide a real way to integrate the Adaptive cards with the Angular App?
https://stackblitz.com/edit/angular-ivy-mfde8r?file=src/app/app.component.ts

@harikaphanikodali
Copy link

Hi Team,

Does adaptive cards support Javascript string methods?
eg: "url": "${member.photoUrl.replace('.blob.', '.z20.web.')}",

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-Templating no-recent-activity Platform-.NET Platform-JavaScript Bugs or features related to the JavaScript renderer
Projects
None yet
Development

No branches or pull requests