(window.webpackJsonp=window.webpackJsonp||[]).push([[68],{121:function(e,t,n){"use strict";n.r(t),n.d(t,"frontMatter",(function(){return c})),n.d(t,"metadata",(function(){return o})),n.d(t,"rightToc",(function(){return p})),n.d(t,"default",(function(){return b}));var a=n(2),i=n(6),r=(n(0),n(313)),c={title:"Data-binding"},o={unversionedId:"expressions",id:"expressions",isDocsHomePage:!1,title:"Data-binding",description:"Some cards in the Wave SDK support data-binding expressions, a mini language that allows computing a card's attribute from the card's data.",source:"@site/docs/expressions.md",slug:"/expressions",permalink:"/wave/docs/expressions",editUrl:"https://github.com/h2oai/wave/edit/master/website/docs/expressions.md",version:"current",sidebar:"someSidebar",previous:{title:"Background Tasks",permalink:"/wave/docs/background"},next:{title:"Files",permalink:"/wave/docs/files"}},p=[{value:"Rationale",id:"rationale",children:[]},{value:"Syntax",id:"syntax",children:[]},{value:"Functions",id:"functions",children:[]}],l={rightToc:p};function b(e){var t=e.components,n=Object(i.a)(e,["components"]);return Object(r.b)("wrapper",Object(a.a)({},l,n,{components:t,mdxType:"MDXLayout"}),Object(r.b)("p",null,"Some cards in the Wave SDK support ",Object(r.b)("em",{parentName:"p"},"data-binding expressions"),", a mini language that allows computing a card's attribute from the card's data."),Object(r.b)("h2",{id:"rationale"},"Rationale"),Object(r.b)("p",null,"A card's attribute can be set directly when created:"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-py",metastring:"{4}","{4}":!0}),"card = page.add(f'donut', ui.small_stat_card(\n    box='1 1 2 2',\n    title='Donut',\n    value='2.99',\n))\n")),Object(r.b)("p",null,"The attribute can be updated later using:"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-py",metastring:"{1}","{1}":!0}),"card.value = '3.49'\n")),Object(r.b)("p",null,"The above approach works fine, but sometimes it's prudent to separate the data (what is displayed) from the presentation (how it is displayed). This is especially important if you care about ",Object(r.b)("a",Object(a.a)({parentName:"p"},{href:"https://en.wikipedia.org/wiki/Internationalization_and_localization"}),"internationalization")," and displaying language-sensitive number, date, and time formatting."),Object(r.b)("p",null,"The above example can be rewritten by pulling the donut price out into ",Object(r.b)("inlineCode",{parentName:"p"},"data"),", and pointing the ",Object(r.b)("inlineCode",{parentName:"p"},"value")," to the ",Object(r.b)("inlineCode",{parentName:"p"},"data")," using an expression:"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-py",metastring:"{4-5}","{4-5}":!0}),"card = page.add(f'donut', ui.small_stat_card(\n    box='1 1 2 2',\n    title='Donut',\n    value='=${{intl price minimum_fraction_digits=2 maximum_fraction_digits=2}}',\n    data=dict(price=2.99),\n))\n")),Object(r.b)("p",null,"The attribute can be update later using:"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-py"}),"card.data.price = 3.49\n")),Object(r.b)("h2",{id:"syntax"},"Syntax"),Object(r.b)("p",null,"Data-binding expressions are indicated with a leading ",Object(r.b)("inlineCode",{parentName:"p"},"=")," (similar to spreadsheet formulae). For example, ",Object(r.b)("inlineCode",{parentName:"p"},"'={{price}}'")," is an expression, but ",Object(r.b)("inlineCode",{parentName:"p"},"'{{price}}'")," is not."),Object(r.b)("p",null,"Placeholders are enclosed between ",Object(r.b)("inlineCode",{parentName:"p"},"{{")," and ",Object(r.b)("inlineCode",{parentName:"p"},"}}"),". The placeholder ",Object(r.b)("inlineCode",{parentName:"p"},"price")," in ",Object(r.b)("inlineCode",{parentName:"p"},"={{price}}")," points to ",Object(r.b)("inlineCode",{parentName:"p"},"data.price"),". If ",Object(r.b)("inlineCode",{parentName:"p"},"data.price")," is ",Object(r.b)("inlineCode",{parentName:"p"},"2.99"),":"),Object(r.b)("ul",null,Object(r.b)("li",{parentName:"ul"},Object(r.b)("inlineCode",{parentName:"li"},"={{price}}")," translates to ",Object(r.b)("inlineCode",{parentName:"li"},"2.99"),". "),Object(r.b)("li",{parentName:"ul"},Object(r.b)("inlineCode",{parentName:"li"},"=${{price}}")," translates to ",Object(r.b)("inlineCode",{parentName:"li"},"$2.99"),". "),Object(r.b)("li",{parentName:"ul"},Object(r.b)("inlineCode",{parentName:"li"},"=Donuts cost ${{price}}")," translates to ",Object(r.b)("inlineCode",{parentName:"li"},"Donuts cost $2.99"),". ")),Object(r.b)("p",null,"An expression can have multiple placeholders. For example, ",Object(r.b)("inlineCode",{parentName:"p"},"={{product}} costs {{price}}")),Object(r.b)("p",null,"If an expression has a placeholder and nothing else, the ",Object(r.b)("inlineCode",{parentName:"p"},"{{")," and ",Object(r.b)("inlineCode",{parentName:"p"},"}}")," can be elided. For example, ",Object(r.b)("inlineCode",{parentName:"p"},"=price")," is shorthand for ",Object(r.b)("inlineCode",{parentName:"p"},"={{price}}"),"."),Object(r.b)("p",null,"Functions can be applied to placeholders using the general form ",Object(r.b)("inlineCode",{parentName:"p"},"{{function_name placeholder param1=arg1 param2=arg2 ...}}"),". For example ",Object(r.b)("inlineCode",{parentName:"p"},"{{intl price minimum_fraction_digits=2 maximum_fraction_digits=2}}")," applies the formatting function ",Object(r.b)("inlineCode",{parentName:"p"},"intl")," to ",Object(r.b)("inlineCode",{parentName:"p"},"price")," with arguments ",Object(r.b)("inlineCode",{parentName:"p"},"minimum_fraction_digits=2")," and ",Object(r.b)("inlineCode",{parentName:"p"},"maximum_fraction_digits=2"),"."),Object(r.b)("h2",{id:"functions"},"Functions"),Object(r.b)("p",null,"Expressions currently support only one function, ",Object(r.b)("inlineCode",{parentName:"p"},"intl"),", which provides language-sensitive number, date, and time formatting using the ",Object(r.b)("a",Object(a.a)({parentName:"p"},{href:"https://tc39.es/ecma402/"}),"ECMAScript Internationalization API"),"."),Object(r.b)("div",{className:"admonition admonition-tip alert alert--success"},Object(r.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(r.b)("h5",{parentName:"div"},Object(r.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(r.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"12",height:"16",viewBox:"0 0 12 16"}),Object(r.b)("path",Object(a.a)({parentName:"svg"},{fillRule:"evenodd",d:"M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"})))),"tip")),Object(r.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(r.b)("p",{parentName:"div"},"Options in the ",Object(r.b)("a",Object(a.a)({parentName:"p"},{href:"https://tc39.es/ecma402/"}),"Internationalization API")," are ",Object(r.b)("inlineCode",{parentName:"p"},"camelCased"),", but you can use both ",Object(r.b)("inlineCode",{parentName:"p"},"camelCased")," and ",Object(r.b)("inlineCode",{parentName:"p"},"snake_cased")," options in data-binding expressions. For example, both ",Object(r.b)("inlineCode",{parentName:"p"},"maximum_fraction_digits")," and ",Object(r.b)("inlineCode",{parentName:"p"},"maximumFractionDigits")," are valid."))))}b.isMDXComponent=!0},313:function(e,t,n){"use strict";n.d(t,"a",(function(){return s})),n.d(t,"b",(function(){return u}));var a=n(0),i=n.n(a);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function c(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function o(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?c(Object(n),!0).forEach((function(t){r(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):c(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function p(e,t){if(null==e)return{};var n,a,i=function(e,t){if(null==e)return{};var n,a,i={},r=Object.keys(e);for(a=0;a<r.length;a++)n=r[a],t.indexOf(n)>=0||(i[n]=e[n]);return i}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(a=0;a<r.length;a++)n=r[a],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}var l=i.a.createContext({}),b=function(e){var t=i.a.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):o(o({},t),e)),n},s=function(e){var t=b(e.components);return i.a.createElement(l.Provider,{value:t},e.children)},d={inlineCode:"code",wrapper:function(e){var t=e.children;return i.a.createElement(i.a.Fragment,{},t)}},m=i.a.forwardRef((function(e,t){var n=e.components,a=e.mdxType,r=e.originalType,c=e.parentName,l=p(e,["components","mdxType","originalType","parentName"]),s=b(n),m=a,u=s["".concat(c,".").concat(m)]||s[m]||d[m]||r;return n?i.a.createElement(u,o(o({ref:t},l),{},{components:n})):i.a.createElement(u,o({ref:t},l))}));function u(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var r=n.length,c=new Array(r);c[0]=m;var o={};for(var p in t)hasOwnProperty.call(t,p)&&(o[p]=t[p]);o.originalType=e,o.mdxType="string"==typeof e?e:a,c[1]=o;for(var l=2;l<r;l++)c[l]=n[l];return i.a.createElement.apply(null,c)}return i.a.createElement.apply(null,n)}m.displayName="MDXCreateElement"}}]);