Expression Functions within Lightning Web Components
How can expression functions similar to Visualforce and Lightning Aura Components be achieved within lightning web components?
For example, <template if:true={index % 5 == 0}><br></template>
expression index % 5 == 0
is not compyling at all.
accountList.html
<template>
<template if:true={accounts.data}>
<template for:each={accounts.data} for:item='item' for:index='index'>
<!--LWC DOES NOT SUPPORT EXPRESSION FUNCTIONS-->
<!--<template if:true={index % 5 == 0}><br></template>-->
{item}
</template>
</template>
</template>
accountList.js
import {LightningElement, wire, track} from 'lwc';
import getAccounts from '@salesforce/apex/TestController.getAccounts';
export default class AccountList extends LightningElement {
@wire(getAccounts) accounts;
}
Since LWC doesn't support Expression Functions, I'd like to know how to work around this restriction.
lightning-web-components expressions
add a comment |
How can expression functions similar to Visualforce and Lightning Aura Components be achieved within lightning web components?
For example, <template if:true={index % 5 == 0}><br></template>
expression index % 5 == 0
is not compyling at all.
accountList.html
<template>
<template if:true={accounts.data}>
<template for:each={accounts.data} for:item='item' for:index='index'>
<!--LWC DOES NOT SUPPORT EXPRESSION FUNCTIONS-->
<!--<template if:true={index % 5 == 0}><br></template>-->
{item}
</template>
</template>
</template>
accountList.js
import {LightningElement, wire, track} from 'lwc';
import getAccounts from '@salesforce/apex/TestController.getAccounts';
export default class AccountList extends LightningElement {
@wire(getAccounts) accounts;
}
Since LWC doesn't support Expression Functions, I'd like to know how to work around this restriction.
lightning-web-components expressions
I have raised this as an idea, you can upvote it success.salesforce.com/ideaView?id=0873A000000EC3gQAG
– Pranay Jaiswal
Jan 4 at 16:07
add a comment |
How can expression functions similar to Visualforce and Lightning Aura Components be achieved within lightning web components?
For example, <template if:true={index % 5 == 0}><br></template>
expression index % 5 == 0
is not compyling at all.
accountList.html
<template>
<template if:true={accounts.data}>
<template for:each={accounts.data} for:item='item' for:index='index'>
<!--LWC DOES NOT SUPPORT EXPRESSION FUNCTIONS-->
<!--<template if:true={index % 5 == 0}><br></template>-->
{item}
</template>
</template>
</template>
accountList.js
import {LightningElement, wire, track} from 'lwc';
import getAccounts from '@salesforce/apex/TestController.getAccounts';
export default class AccountList extends LightningElement {
@wire(getAccounts) accounts;
}
Since LWC doesn't support Expression Functions, I'd like to know how to work around this restriction.
lightning-web-components expressions
How can expression functions similar to Visualforce and Lightning Aura Components be achieved within lightning web components?
For example, <template if:true={index % 5 == 0}><br></template>
expression index % 5 == 0
is not compyling at all.
accountList.html
<template>
<template if:true={accounts.data}>
<template for:each={accounts.data} for:item='item' for:index='index'>
<!--LWC DOES NOT SUPPORT EXPRESSION FUNCTIONS-->
<!--<template if:true={index % 5 == 0}><br></template>-->
{item}
</template>
</template>
</template>
accountList.js
import {LightningElement, wire, track} from 'lwc';
import getAccounts from '@salesforce/apex/TestController.getAccounts';
export default class AccountList extends LightningElement {
@wire(getAccounts) accounts;
}
Since LWC doesn't support Expression Functions, I'd like to know how to work around this restriction.
lightning-web-components expressions
lightning-web-components expressions
edited Jan 4 at 9:48
Oleksandr Berehovskyi
10.3k32339
10.3k32339
asked Dec 21 '18 at 15:24
Oleh BerehovskyiOleh Berehovskyi
384114
384114
I have raised this as an idea, you can upvote it success.salesforce.com/ideaView?id=0873A000000EC3gQAG
– Pranay Jaiswal
Jan 4 at 16:07
add a comment |
I have raised this as an idea, you can upvote it success.salesforce.com/ideaView?id=0873A000000EC3gQAG
– Pranay Jaiswal
Jan 4 at 16:07
I have raised this as an idea, you can upvote it success.salesforce.com/ideaView?id=0873A000000EC3gQAG
– Pranay Jaiswal
Jan 4 at 16:07
I have raised this as an idea, you can upvote it success.salesforce.com/ideaView?id=0873A000000EC3gQAG
– Pranay Jaiswal
Jan 4 at 16:07
add a comment |
3 Answers
3
active
oldest
votes
There are multiple options. First, note, that all computations are in JavaScript, not in the markup.
Option 1
You implement the display of your {item} (which is currently only the JSON object), into a dedicated component AccountListItem
. And implement in there the logic that @POZ suggested.
Something along the lines of:
import {LightningElement, api} from 'lwc';
export default class AccountListItem extends LightningElement {
@api index;
@api item;
get isMod5() {
return this.index % 5 == 0;
}
}
Option 2
You use a wired function instead of a wired property. And then do some fun stuff with a changed data model. Although this is hacky.
import {LightningElement, wire, track} from 'lwc';
import getAccounts from '@salesforce/apex/TestController.getAccounts';
export default class AccountList extends LightningElement {
@wire(getAccounts)
wiredAccounts({ error, data}) {
if (error) {
// do error handling, please
} else if (data) {
this.accounts = data.map((acct, index) => {
return {
acct: acct,
isMod5: index % 5 == 0 ? true : false
}
})
}
}
add a comment |
EDIT: changed my answer because previous one was wrong:
You have to write a JS expression that paginates your list like this:
get getContacts() {
return [
['a', 'b', 'c', 'd', 'e'], // Page 0, max 5 item
['f', 'g'], // Page 1
];
}
Then use two iterations in your template:
<template for:each={getContacts} for:item="page">
<template for:each={page} for:item="contact">
{contact}
</template>
</template>
2
How doesindex
get passed to this function?
– Jayant Das
Dec 21 '18 at 17:26
Thanks for pointing this out @JayantDas, I've edited my answer.
– POZ
Dec 21 '18 at 17:41
add a comment |
Because expressions are not allowed in Lightning Web Component template, you would have required a JavaScript getter
function here. Refer to HTML Template Directives documentation for details.
Excerpt below from documentation:
if:true|false={expression}
..... (some text omitted)
The engine doesn’t allow computed expressions. To compute the value of expression, use a getter in the JavaScript class.
But, in your case you need to pass the index
var in the iteration, so even having a getter function doesn't seem to do the job here.
I am not completely sure of the use case here as why you want to utilize the index
within the iteration, but as I don't see a way to set the index
to a JS function, here's an approach that you can take by utilizing Composition.
Even though this approach solves the problem here, but still seems to be an overhead of creating another component to achieve this what could have been achieved inline.
The approach here is:
- Create a custom LWC
- Pass the index value to the component within the iteration in the parent component
- Compute the value of the index within that component and perform your required operation
Let's say I create a custom LWC as c-my-index-component
, which looks like as below:
<template>
<template if:true={indexVar}>
// do something
</template>
</template>
In the JS, I have this property defined as:
import { LightningElement, api, track } from 'lwc';
export default class MyCustomIndex extends LightningElement {
@track myVariable;
set indexVar(value) {
this.myVariable = value;
}
@api
get indexVar() {
return (this.myVariable % 5 === 0)
}
}
And then finally I use it in my existing component in iteration as below:
<template for:each={accounts.data} for:item='item' for:index='index'>
<c-my-index-component key={item.Id} index-var={index}></c-my-index-component>
// my other code
</template>
add a comment |
Your Answer
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "459"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsalesforce.stackexchange.com%2fquestions%2f244460%2fexpression-functions-within-lightning-web-components%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
There are multiple options. First, note, that all computations are in JavaScript, not in the markup.
Option 1
You implement the display of your {item} (which is currently only the JSON object), into a dedicated component AccountListItem
. And implement in there the logic that @POZ suggested.
Something along the lines of:
import {LightningElement, api} from 'lwc';
export default class AccountListItem extends LightningElement {
@api index;
@api item;
get isMod5() {
return this.index % 5 == 0;
}
}
Option 2
You use a wired function instead of a wired property. And then do some fun stuff with a changed data model. Although this is hacky.
import {LightningElement, wire, track} from 'lwc';
import getAccounts from '@salesforce/apex/TestController.getAccounts';
export default class AccountList extends LightningElement {
@wire(getAccounts)
wiredAccounts({ error, data}) {
if (error) {
// do error handling, please
} else if (data) {
this.accounts = data.map((acct, index) => {
return {
acct: acct,
isMod5: index % 5 == 0 ? true : false
}
})
}
}
add a comment |
There are multiple options. First, note, that all computations are in JavaScript, not in the markup.
Option 1
You implement the display of your {item} (which is currently only the JSON object), into a dedicated component AccountListItem
. And implement in there the logic that @POZ suggested.
Something along the lines of:
import {LightningElement, api} from 'lwc';
export default class AccountListItem extends LightningElement {
@api index;
@api item;
get isMod5() {
return this.index % 5 == 0;
}
}
Option 2
You use a wired function instead of a wired property. And then do some fun stuff with a changed data model. Although this is hacky.
import {LightningElement, wire, track} from 'lwc';
import getAccounts from '@salesforce/apex/TestController.getAccounts';
export default class AccountList extends LightningElement {
@wire(getAccounts)
wiredAccounts({ error, data}) {
if (error) {
// do error handling, please
} else if (data) {
this.accounts = data.map((acct, index) => {
return {
acct: acct,
isMod5: index % 5 == 0 ? true : false
}
})
}
}
add a comment |
There are multiple options. First, note, that all computations are in JavaScript, not in the markup.
Option 1
You implement the display of your {item} (which is currently only the JSON object), into a dedicated component AccountListItem
. And implement in there the logic that @POZ suggested.
Something along the lines of:
import {LightningElement, api} from 'lwc';
export default class AccountListItem extends LightningElement {
@api index;
@api item;
get isMod5() {
return this.index % 5 == 0;
}
}
Option 2
You use a wired function instead of a wired property. And then do some fun stuff with a changed data model. Although this is hacky.
import {LightningElement, wire, track} from 'lwc';
import getAccounts from '@salesforce/apex/TestController.getAccounts';
export default class AccountList extends LightningElement {
@wire(getAccounts)
wiredAccounts({ error, data}) {
if (error) {
// do error handling, please
} else if (data) {
this.accounts = data.map((acct, index) => {
return {
acct: acct,
isMod5: index % 5 == 0 ? true : false
}
})
}
}
There are multiple options. First, note, that all computations are in JavaScript, not in the markup.
Option 1
You implement the display of your {item} (which is currently only the JSON object), into a dedicated component AccountListItem
. And implement in there the logic that @POZ suggested.
Something along the lines of:
import {LightningElement, api} from 'lwc';
export default class AccountListItem extends LightningElement {
@api index;
@api item;
get isMod5() {
return this.index % 5 == 0;
}
}
Option 2
You use a wired function instead of a wired property. And then do some fun stuff with a changed data model. Although this is hacky.
import {LightningElement, wire, track} from 'lwc';
import getAccounts from '@salesforce/apex/TestController.getAccounts';
export default class AccountList extends LightningElement {
@wire(getAccounts)
wiredAccounts({ error, data}) {
if (error) {
// do error handling, please
} else if (data) {
this.accounts = data.map((acct, index) => {
return {
acct: acct,
isMod5: index % 5 == 0 ? true : false
}
})
}
}
edited Dec 21 '18 at 17:41
codeyinthecloud
3,5901428
3,5901428
answered Dec 21 '18 at 17:39
muenzpraegermuenzpraeger
23911
23911
add a comment |
add a comment |
EDIT: changed my answer because previous one was wrong:
You have to write a JS expression that paginates your list like this:
get getContacts() {
return [
['a', 'b', 'c', 'd', 'e'], // Page 0, max 5 item
['f', 'g'], // Page 1
];
}
Then use two iterations in your template:
<template for:each={getContacts} for:item="page">
<template for:each={page} for:item="contact">
{contact}
</template>
</template>
2
How doesindex
get passed to this function?
– Jayant Das
Dec 21 '18 at 17:26
Thanks for pointing this out @JayantDas, I've edited my answer.
– POZ
Dec 21 '18 at 17:41
add a comment |
EDIT: changed my answer because previous one was wrong:
You have to write a JS expression that paginates your list like this:
get getContacts() {
return [
['a', 'b', 'c', 'd', 'e'], // Page 0, max 5 item
['f', 'g'], // Page 1
];
}
Then use two iterations in your template:
<template for:each={getContacts} for:item="page">
<template for:each={page} for:item="contact">
{contact}
</template>
</template>
2
How doesindex
get passed to this function?
– Jayant Das
Dec 21 '18 at 17:26
Thanks for pointing this out @JayantDas, I've edited my answer.
– POZ
Dec 21 '18 at 17:41
add a comment |
EDIT: changed my answer because previous one was wrong:
You have to write a JS expression that paginates your list like this:
get getContacts() {
return [
['a', 'b', 'c', 'd', 'e'], // Page 0, max 5 item
['f', 'g'], // Page 1
];
}
Then use two iterations in your template:
<template for:each={getContacts} for:item="page">
<template for:each={page} for:item="contact">
{contact}
</template>
</template>
EDIT: changed my answer because previous one was wrong:
You have to write a JS expression that paginates your list like this:
get getContacts() {
return [
['a', 'b', 'c', 'd', 'e'], // Page 0, max 5 item
['f', 'g'], // Page 1
];
}
Then use two iterations in your template:
<template for:each={getContacts} for:item="page">
<template for:each={page} for:item="contact">
{contact}
</template>
</template>
edited Dec 21 '18 at 17:39
answered Dec 21 '18 at 17:17
POZPOZ
1,344311
1,344311
2
How doesindex
get passed to this function?
– Jayant Das
Dec 21 '18 at 17:26
Thanks for pointing this out @JayantDas, I've edited my answer.
– POZ
Dec 21 '18 at 17:41
add a comment |
2
How doesindex
get passed to this function?
– Jayant Das
Dec 21 '18 at 17:26
Thanks for pointing this out @JayantDas, I've edited my answer.
– POZ
Dec 21 '18 at 17:41
2
2
How does
index
get passed to this function?– Jayant Das
Dec 21 '18 at 17:26
How does
index
get passed to this function?– Jayant Das
Dec 21 '18 at 17:26
Thanks for pointing this out @JayantDas, I've edited my answer.
– POZ
Dec 21 '18 at 17:41
Thanks for pointing this out @JayantDas, I've edited my answer.
– POZ
Dec 21 '18 at 17:41
add a comment |
Because expressions are not allowed in Lightning Web Component template, you would have required a JavaScript getter
function here. Refer to HTML Template Directives documentation for details.
Excerpt below from documentation:
if:true|false={expression}
..... (some text omitted)
The engine doesn’t allow computed expressions. To compute the value of expression, use a getter in the JavaScript class.
But, in your case you need to pass the index
var in the iteration, so even having a getter function doesn't seem to do the job here.
I am not completely sure of the use case here as why you want to utilize the index
within the iteration, but as I don't see a way to set the index
to a JS function, here's an approach that you can take by utilizing Composition.
Even though this approach solves the problem here, but still seems to be an overhead of creating another component to achieve this what could have been achieved inline.
The approach here is:
- Create a custom LWC
- Pass the index value to the component within the iteration in the parent component
- Compute the value of the index within that component and perform your required operation
Let's say I create a custom LWC as c-my-index-component
, which looks like as below:
<template>
<template if:true={indexVar}>
// do something
</template>
</template>
In the JS, I have this property defined as:
import { LightningElement, api, track } from 'lwc';
export default class MyCustomIndex extends LightningElement {
@track myVariable;
set indexVar(value) {
this.myVariable = value;
}
@api
get indexVar() {
return (this.myVariable % 5 === 0)
}
}
And then finally I use it in my existing component in iteration as below:
<template for:each={accounts.data} for:item='item' for:index='index'>
<c-my-index-component key={item.Id} index-var={index}></c-my-index-component>
// my other code
</template>
add a comment |
Because expressions are not allowed in Lightning Web Component template, you would have required a JavaScript getter
function here. Refer to HTML Template Directives documentation for details.
Excerpt below from documentation:
if:true|false={expression}
..... (some text omitted)
The engine doesn’t allow computed expressions. To compute the value of expression, use a getter in the JavaScript class.
But, in your case you need to pass the index
var in the iteration, so even having a getter function doesn't seem to do the job here.
I am not completely sure of the use case here as why you want to utilize the index
within the iteration, but as I don't see a way to set the index
to a JS function, here's an approach that you can take by utilizing Composition.
Even though this approach solves the problem here, but still seems to be an overhead of creating another component to achieve this what could have been achieved inline.
The approach here is:
- Create a custom LWC
- Pass the index value to the component within the iteration in the parent component
- Compute the value of the index within that component and perform your required operation
Let's say I create a custom LWC as c-my-index-component
, which looks like as below:
<template>
<template if:true={indexVar}>
// do something
</template>
</template>
In the JS, I have this property defined as:
import { LightningElement, api, track } from 'lwc';
export default class MyCustomIndex extends LightningElement {
@track myVariable;
set indexVar(value) {
this.myVariable = value;
}
@api
get indexVar() {
return (this.myVariable % 5 === 0)
}
}
And then finally I use it in my existing component in iteration as below:
<template for:each={accounts.data} for:item='item' for:index='index'>
<c-my-index-component key={item.Id} index-var={index}></c-my-index-component>
// my other code
</template>
add a comment |
Because expressions are not allowed in Lightning Web Component template, you would have required a JavaScript getter
function here. Refer to HTML Template Directives documentation for details.
Excerpt below from documentation:
if:true|false={expression}
..... (some text omitted)
The engine doesn’t allow computed expressions. To compute the value of expression, use a getter in the JavaScript class.
But, in your case you need to pass the index
var in the iteration, so even having a getter function doesn't seem to do the job here.
I am not completely sure of the use case here as why you want to utilize the index
within the iteration, but as I don't see a way to set the index
to a JS function, here's an approach that you can take by utilizing Composition.
Even though this approach solves the problem here, but still seems to be an overhead of creating another component to achieve this what could have been achieved inline.
The approach here is:
- Create a custom LWC
- Pass the index value to the component within the iteration in the parent component
- Compute the value of the index within that component and perform your required operation
Let's say I create a custom LWC as c-my-index-component
, which looks like as below:
<template>
<template if:true={indexVar}>
// do something
</template>
</template>
In the JS, I have this property defined as:
import { LightningElement, api, track } from 'lwc';
export default class MyCustomIndex extends LightningElement {
@track myVariable;
set indexVar(value) {
this.myVariable = value;
}
@api
get indexVar() {
return (this.myVariable % 5 === 0)
}
}
And then finally I use it in my existing component in iteration as below:
<template for:each={accounts.data} for:item='item' for:index='index'>
<c-my-index-component key={item.Id} index-var={index}></c-my-index-component>
// my other code
</template>
Because expressions are not allowed in Lightning Web Component template, you would have required a JavaScript getter
function here. Refer to HTML Template Directives documentation for details.
Excerpt below from documentation:
if:true|false={expression}
..... (some text omitted)
The engine doesn’t allow computed expressions. To compute the value of expression, use a getter in the JavaScript class.
But, in your case you need to pass the index
var in the iteration, so even having a getter function doesn't seem to do the job here.
I am not completely sure of the use case here as why you want to utilize the index
within the iteration, but as I don't see a way to set the index
to a JS function, here's an approach that you can take by utilizing Composition.
Even though this approach solves the problem here, but still seems to be an overhead of creating another component to achieve this what could have been achieved inline.
The approach here is:
- Create a custom LWC
- Pass the index value to the component within the iteration in the parent component
- Compute the value of the index within that component and perform your required operation
Let's say I create a custom LWC as c-my-index-component
, which looks like as below:
<template>
<template if:true={indexVar}>
// do something
</template>
</template>
In the JS, I have this property defined as:
import { LightningElement, api, track } from 'lwc';
export default class MyCustomIndex extends LightningElement {
@track myVariable;
set indexVar(value) {
this.myVariable = value;
}
@api
get indexVar() {
return (this.myVariable % 5 === 0)
}
}
And then finally I use it in my existing component in iteration as below:
<template for:each={accounts.data} for:item='item' for:index='index'>
<c-my-index-component key={item.Id} index-var={index}></c-my-index-component>
// my other code
</template>
edited Dec 21 '18 at 20:54
answered Dec 21 '18 at 15:46
Jayant DasJayant Das
17.2k21330
17.2k21330
add a comment |
add a comment |
Thanks for contributing an answer to Salesforce Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsalesforce.stackexchange.com%2fquestions%2f244460%2fexpression-functions-within-lightning-web-components%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
I have raised this as an idea, you can upvote it success.salesforce.com/ideaView?id=0873A000000EC3gQAG
– Pranay Jaiswal
Jan 4 at 16:07