You need to sign in to do that
Don't have an account?
Christian Schwabe (x)
LWC: Lightning record page is not loading with custom lwc
Hi everyone
I build a custom lightning web component (lwc) with a datatable and a wire-function with an apex-controller.
If i place the lwc on the lightnig record page an error appears:
Looks like there's a problem.
Unfortunately, there was a problem. Please try again. If the problem continues, get in touch with your administrator with the error ID shown here and any other related details. An internal server error has occurred Error ID: 747686150-78663 (1184503911)
Here is a screenshot with the error: https://i.imgur.com/3Ov7PnQ.png
No error in debug log and no error is shown up in browser-console.
I have no reason why this happen. Has anyone some suggestions?
rssFeed.html:
rssFeed.js:
rssFeed.js-meta.xml:
Here is the apex-controller:
I build a custom lightning web component (lwc) with a datatable and a wire-function with an apex-controller.
If i place the lwc on the lightnig record page an error appears:
Looks like there's a problem.
Unfortunately, there was a problem. Please try again. If the problem continues, get in touch with your administrator with the error ID shown here and any other related details. An internal server error has occurred Error ID: 747686150-78663 (1184503911)
Here is a screenshot with the error: https://i.imgur.com/3Ov7PnQ.png
No error in debug log and no error is shown up in browser-console.
I have no reason why this happen. Has anyone some suggestions?
rssFeed.html:
<template> <div class={flexipageRegionWidth}> <div class="slds-m-top_medium slds-m-bottom_x-large"> <!-- Simple --> <template if:true={data}> <div class="slds-p-around_medium lgc-bg"> <lightning-datatable key-field="id" data={data} columns={columns} is-loading={tableLoadingState} hide-checkbox-column={hideCheckboxColumn}> </lightning-datatable> </div> </template> </div> <!-- Data failed to load --> <template if:false={data}> <div class="slds-text-color_error"> An error occurred while loading. </div> </template> </div> </template>
rssFeed.js:
import { LightningElement, wire, track, api } from 'lwc'; import { getObjectInfo } from 'lightning/uiObjectInfoApi'; // https://developer.salesforce.com/docs/component-library/documentation/lwc/lwc.reference_wire_adapters_object_info import RSSFEED_OBJECT from '@salesforce/schema/RSSFeed__c'; import getFilteredRssFeeds from '@salesforce/apex/RssFeedController.getFilteredRssFeeds'; export default class RssFeed extends LightningElement { @api flexipageRegionWidth; // https://developer.salesforce.com/docs/component-library/documentation/lwc/use_width_aware @api recordId;// Public property. Id of brand-record. @api columnNames = undefined; // Public property. Set by lightning app builder. objectInfo = undefined; // hideCheckboxColumn = true; // If true, the checkbox column for row selection is hidden. @track data; @track error; @track columns; @track tableLoadingState = true; @wire(getObjectInfo, { objectApiName: RSSFEED_OBJECT }) wireObjectInfo({error, data}){ console.log('>>>wireObjectInfo called.'); if (data) { console.log('>>>data: ' + JSON.stringify(data, null, '\t')); this.objectInfo = data; this.error = undefined; this._prepareTableColumns(); } else if (error) { console.error('>>>error: ' + JSON.stringify(error, null, '\t')); this.error = error; this.objectInfo = undefined; } } @wire(getFilteredRssFeeds, { brandId: '$recordId' }) wiredFilteredRssFeeds({error, data}){ console.log('>>>wiredFilteredRssFeeds called.'); if (data) { console.log('>>>' + JSON.stringify(data, null, '\t')); this.data = data; this.error = undefined; } else if (error) { console.error('>>>' + JSON.stringify(error, null, '\t')); this.error = error; this.data = undefined; } } _prepareTableColumns(){ console.log('>>>_prepareTableColumns called.'); this.columns.forEach(column => { let columnLabel = ((this.objectInfo) ? this.objectInfo.fields[column.fieldName].label : ''); column.label = columnLabel; console.log('>>>column' + JSON.stringify(column, null, '\t')); }); } /** * https://developer.salesforce.com/docs/component-library/documentation/lwc/create_lifecycle_hooks_dom.html * The connectedCallback() lifecycle hook fires when a component is inserted into the DOM. */ async connectedCallback() { console.log('>>>async connectedCallback called.'); this.tableLoadingState = false; console.log('>>>this.columnNames: ' + this.columnNames); this.columns = JSON.parse(this.columnNames); console.log('>>>this.columns: ' + JSON.stringify(this.columns, null, '\t')); } }
rssFeed.js-meta.xml:
<?xml version="1.0" encoding="UTF-8"?> <LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata" fqn="RssFeed"> <apiVersion>46.0</apiVersion> <isExposed>true</isExposed> <targets> <target>lightning__RecordPage</target> </targets> <targetConfigs> <targetConfig targets="lightning__RecordPage"> <property default="[{ 'label': 'Title', 'fieldName': 'Title__c' },{ 'label': 'Description', 'fieldName': 'Description__c' },{ 'label': 'Link', 'fieldName': 'Link__c', 'type': 'url', 'fixedWidth': 200 },{ 'label': 'Date', 'fieldName': 'Date__c', 'type': 'date', 'fixedWidth': 100 }]" description="Specifies which columns are displayed." label="Column Names" name="columnNames" required="true" type="String"/> <objects> <object>Brand__c</object> </objects> </targetConfig> </targetConfigs> </LightningComponentBundle>
Here is the apex-controller:
/** * Is used for lightning web component (lwc) named rssFeed. * Query relevant rss feed filtered by Id of Brand (Brand__c). * * @author: <Christian Schwabe> (Christian.Schwabe@colliers.com) * * @history: * version | author | changes * ==================================================================================== * 0.1 08.05.2019 | Christian Schwabe (Christian.Schwabe@colliers.com) | initial version. */ public with sharing class RssFeedController { /** * Query RSS-Feed records filtered by Id for Brand (Brand__c). * * @param brandId Id for Brand (Brand__c) * * @return List<Brand__> */ @AuraEnabled(cacheable=true) public static List<RSSFeed__c> getFilteredRssFeeds(Id brandId){ List<RSSFeed__c> listOfRssFeed = new List<RSSFeed__c>(); for(RSSFeed__c rssFeed : [SELECT Id, Link__c, Title__c, Author__c, Description__c, Date__c FROM RSSFeed__c WHERE Brand__c = :brandId]){ rssFeed.Description__c = String.valueOf(rssFeed.Description__c).stripHtmlTags(); listOfRssFeed.add(rssFeed); } return listOfRssFeed; } }
As you already noticed as soon as the format is correct for a JSON message, all seems correct for the Ligthning App Builder but that failed each time nevertheless when we wanted to see the page.
I made many tests and it is just the complicated format of the message that created the error.
A simple workaround is too encode/decode the string with ( encodeURI and decodeURI standard functions of JS ).
Another important point: these properties of the targetConfig are very "persistent" as soon as they are used by a page.
The advice is to remove the component from the page under the Lex App Builder before reploying the new code from VS Code if you made some changes on the properties via targetConfig only ( otherwise you will spend more time with unsuccesful tries, deployment partial or blocked by the pages probably ).
There are probably many other techniques for encoding/decoding a message in JS (decodeURI/encodeURI) but this easy technique seems sufficient.
So excepted, these two minor points all your sophisticated code works fine and ... will be useful for me in the future.
All Answers
There is a first thing to check with the format of a parsable string in JSON.
The difference is subtle.
Test in the playground: "columns" works and "columns2" doesn't.
https://developer.salesforce.com/docs/component-library/tools/playground/Hka1K2TFE/25/edit
But that is just a first step to check towards a proper solution and your code used sphisticated initializations (@wire + this._prepareTableColumns(); ) (second complication probably).
thanks for your help.
I try to figure your tips and make sure to use the syntax for "columns".
The curious thing is that the lwc looks fine during the draft modus in lightning app builder. See following screenshot: https://imgur.com/Kn06rW8
Related to the function call this._prepareTableColumns();
What I try to do is, based on the logged in user, show translated (german/english) table columns.
Anyway: The "Looks like there's a problem."-error still appears.
Best regards,
Christian
Your problem occurs at the early beginning.
Your <property default> contains my const columns2 and in the playground, that doesn't work but there is also a clear error message in the playground that doesn't occur like that with your code.
Did you test exactly the same <property default> in the app builder ?
jQuery.parseJSON single quote vs double quote
https://stackoverflow.com/questions/14355655/jquery-parsejson-single-quote-vs-double-quote
But that is not sufficient probably to solve completely your complicated problem.
I've understand the problem description and your solution for the first time and also changed it exactly how you mentioned.
I removed the default value from the xml structure and now only pass the content from you column-variable via the Lightning App Builder.
Did you notice, that the component rendered correctly during the draft mode in lightning app builder? I think if there was a problem with the json-structure the lwc also does not render correctly in draft but it doesn't. Even if I commented out the @wire to load records from apex-controller the error still occurs.
That should work but that doesn't and as soon as you see the laconic error due to a restriction of "use strict" in the internal JS of Salesfroce nothing seems sufficient to fix the problem afterwards even if you almost empty all your code.
It is interesting to keep the <targetConfigs>.
The idea is to succeed in "debugging" the error that is an internal very complicated error in JS (caller/callee with "use strict" on the field "error").
I failed myself until now.
Could you point me in the right direction?
Where should I dig deeper in?
Did you mean my code is worse? Or did you mean i create an error that should not happen?
How should I debug an error where no error appears?
I will retry tonight step after step until the complete code works because it is an excellent excercise with several complications without being an enorm component at all.
As soon as there is the laconic error, all seems freezed as we need to recreate a new component from scratch (?). You can almost empty your code, there is still the error.
As you already noticed as soon as the format is correct for a JSON message, all seems correct for the Ligthning App Builder but that failed each time nevertheless when we wanted to see the page.
I made many tests and it is just the complicated format of the message that created the error.
A simple workaround is too encode/decode the string with ( encodeURI and decodeURI standard functions of JS ).
Another important point: these properties of the targetConfig are very "persistent" as soon as they are used by a page.
The advice is to remove the component from the page under the Lex App Builder before reploying the new code from VS Code if you made some changes on the properties via targetConfig only ( otherwise you will spend more time with unsuccesful tries, deployment partial or blocked by the pages probably ).
There are probably many other techniques for encoding/decoding a message in JS (decodeURI/encodeURI) but this easy technique seems sufficient.
So excepted, these two minor points all your sophisticated code works fine and ... will be useful for me in the future.
This forum is a good complement of the trailhead modules. The given samples are quite short sometimes including for the LWC recipes.
The LWC recipe explained also in video:
https://github.com/trailheadapps/lwc-recipes/blob/master/force-app/main/default/lwc/compositionWithAppBuilder/compositionWithAppBuilder.js-meta.xml
It is very basic as you can see even if they tested different types and your code shows the limits when we complicate the message (very useful for the future by having a model of code for this specific need that works). They didn't use lightning__RecordPage but that is not the problem.
thank you so much for your time and testing my problem with your heart and soul and solving it for the first instance!
I understand all of your arguments but getting headache when I realize that this workaround is needed to make this lwc work.
On the one hand - without criticizing your solution - the parameter "" in the lightning app builder looks really ugly.
And on the other hand I swear the component works before without this hack and didn't understand why this is needed now!
I also changed the format for the lightning app builder parameter "Column Names" to the following:
[{ "fieldName": "Title__c" },{ "fieldName": "Description__c" },{ "fieldName": "Link__c", "type": "url", "fixedWidth": 200 },{ "fieldName": "Date__c", "type": "date", "fixedWidth": 100 }]
It was not needed to hold the label information for each column because this information is extracted in the function _prepareTableColumns().
I am really, really happy to have this dont with you and find a solution. I couldn't imagine a better start to a working week. Yaaaay!
During ideas to optimize this solution I think about the possibility to use "lightning/uiRecordApi" (exactly: https://developer.salesforce.com/docs/component-library/documentation/lwc/lwc.reference_lightning_ui_api_record) to remove the apex controller. But it seems that this wire adapter only returns one record instead of a list. This idea was only a mental thinking.
I also changed the function wiredFilteredRssFeeds to a two parameter function and added the variable listOfApiName to delegate the selected fields from lightning app builder to select needed fields in apex.
This last change is useful, if any other fields should be displayed / added / removed from the object to NOT change the code and redeploy it.
To extract the needed api name I created a new function called _extractApiNames(); Nothing else is changed now. I swear!
Best regards,
Christian
For completeness - My code looks now like the following:
rssFeed.js-meta.xml
rssFeed.html:
rssFeed.js:
RssFeedController.cls:
Obviously, the encoding of string is not an optimized "nice" solution (longer strings, unreadable,and so on, it is a first try for a first sufficient workaround) but the Lightning App Builder doesn't need it at first. That proofs that your code is correct furthermore globally.
A real session needs this "ugly" workaround so the "Session Settings" (Setup) are more restrictive (or it is just a bug?).
( Clickjack Protection, Cross-Site Request Forgery (CSRF) Protection and so on even if the error seems something else).
These unreadable encoding/decoding strings should be useless and other encoding techniques with the simple still readable result is JSON.stringify() but there is always a problem around the quotes very likely (so you can replace the quotes with anything else perhaps for a still more readable string).I used encodeURI() because it replaces all the quotes by default without a new function to write
String replace should be sufficient for the quotes only. You can try it.
https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Objets_globaux/String/replace.
The simple JSON.stringify() string used at the beginning should have been correct and sufficient (period) and the Lex App Builder accepts it but not the session (?).
The best option is to open a known issue for Salesforce with your code for an official response but that could be quite long (... years sometimes) given that the Lex App Builder accepts the JSON.stringify.
On this other forum: https://salesforce.stackexchange.com/ you could have new options.
A little Revolution for the development with previewing and a better debugging environment with LWC.
Local Development for Lightning Web Components: 25 june 2019
Historically, building components in Salesforce has relied upon a connection to an org. With Lightning Web Components, Salesforce had moved to an open, standards-based approach to development that makes building components locally not only possible, but an excellent experience for rapid iteration and release. In this session, we'll walk you through local development for LWC, introducing you to this new capability for previewing and rendering components from localhost. You'll see live demos and code walkthroughs, and walk away ready to spin up VS Code and enjoy an improved developer experience with rich error handling, local rendering, @wire, and much more!
https://www.youtube.com/watch?v=nygnbZj4EXs
thanks for the reminder and the link to watch the video.
This event was already declared in my calender to be watched today. It is much easier to watch the video than a livestream because you can have a look whenever you want. *thumbs up*
Regards,
Christian