-
Notifications
You must be signed in to change notification settings - Fork 2.1k
feat(instructions): add Salesforce LWC development instructions #530
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
Merged
Merged
Changes from 3 commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
fabc298
Added instructions for Salesforce LWC development
abbas133 f253456
Updated instruction file
abbas133 996a357
Updated instructions
abbas133 0acc20a
Update instructions/lwc.instructions.md
abbas133 751e366
Copilot suggestion updated
abbas133 2163179
Merge branch 'add-lws-instructions' of https://github.com/abbas133/aw…
abbas133 2d36943
Updated instructions to more specific examples for decorators
abbas133 01c9be7
Updated example codes
abbas133 2cff1e2
Update instructions/lwc.instructions.md
abbas133 5e94171
Update instructions/lwc.instructions.md
abbas133 960f40b
Merge branch 'main' into add-lws-instructions
codemillmatt File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,328 @@ | ||
| --- | ||
| description: "Guidelines and best practices for developing Lightning Web Components (LWC) on Salesforce Platform." | ||
| applyTo: "force-app/main/default/lwc/**" | ||
abbas133 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
abbas133 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| --- | ||
|
|
||
| # LWC Development | ||
|
|
||
| ## General Instructions | ||
|
|
||
| - Each LWC should reside in its own folder under `force-app/main/default/lwc/`. | ||
| - The folder name should match the component name (e.g., `myComponent` for `myComponent`). | ||
abbas133 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| - Each component folder should contain the following files: | ||
| - `myComponent.html`: The HTML template file. | ||
| - `myComponent.js`: The JavaScript controller file. | ||
| - `myComponent.js-meta.xml`: The metadata configuration file. | ||
| - Optional: `myComponent.css` for component-specific styles. | ||
| - Optional: `myComponent.test.js` for Jest unit tests. | ||
|
|
||
| ## Core Principles | ||
|
|
||
| ### 1. Use Lightning Components Over HTML Tags | ||
| Always prefer Lightning Web Component library components over plain HTML elements for consistency, accessibility, and future-proofing. | ||
|
|
||
| #### Recommended Approach | ||
| ```html | ||
| <!-- Use Lightning components --> | ||
| <lightning-button label="Save" variant="brand" onclick={handleSave}></lightning-button> | ||
| <lightning-input type="text" label="Name" value={name} onchange={handleNameChange}></lightning-input> | ||
| <lightning-combobox label="Type" options={typeOptions} value={selectedType}></lightning-combobox> | ||
| <lightning-radio-group name="duration" label="Duration" options={durationOptions} value={duration} type="radio"></lightning-radio-group> | ||
| ``` | ||
|
|
||
| #### Avoid Plain HTML | ||
| ```html | ||
| <!-- Avoid these --> | ||
| <button onclick={handleSave}>Save</button> | ||
| <input type="text" onchange={handleNameChange} /> | ||
| <select onchange={handleTypeChange}> | ||
| <option value="option1">Option 1</option> | ||
| </select> | ||
| ``` | ||
|
|
||
| ### 2. Lightning Component Mapping Guide | ||
|
|
||
| | HTML Element | Lightning Component | Key Attributes | | ||
| |--------------|-------------------|----------------| | ||
| | `<button>` | `<lightning-button>` | `variant`, `label`, `icon-name` | | ||
| | `<input>` | `<lightning-input>` | `type`, `label`, `variant` | | ||
| | `<select>` | `<lightning-combobox>` | `options`, `value`, `placeholder` | | ||
| | `<textarea>` | `<lightning-textarea>` | `label`, `max-length` | | ||
| | `<input type="checkbox">` | `<lightning-input type="checkbox">` | `checked`, `label` | | ||
| | `<input type="radio">` | `<lightning-radio-group>` | `options`, `type`, `name` | | ||
| | `<input type="toggle">` | `<lightning-input type="toggle">` | `checked`, `variant` | | ||
| | Custom pills | `<lightning-pill>` | `label`, `name`, `onremove` | | ||
| | Icons | `<lightning-icon>` | `icon-name`, `size`, `variant` | | ||
|
|
||
| ### 3. SLDS2 Design System Compliance | ||
abbas133 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| #### Use SLDS Utility Classes | ||
| Always use Salesforce Lightning Design System utility classes with the `slds-var-` prefix for modern implementations: | ||
|
|
||
| ```html | ||
| <!-- Spacing --> | ||
| <div class="slds-var-m-around_medium slds-var-p-top_large"> | ||
| <div class="slds-var-m-bottom_small">Content</div> | ||
| </div> | ||
|
|
||
| <!-- Layout --> | ||
| <div class="slds-grid slds-wrap slds-gutters_small"> | ||
| <div class="slds-col slds-size_1-of-2 slds-medium-size_1-of-3"> | ||
| <!-- Content --> | ||
| </div> | ||
| </div> | ||
|
|
||
| <!-- Typography --> | ||
| <h2 class="slds-text-heading_medium slds-var-m-bottom_small">Section Title</h2> | ||
| <p class="slds-text-body_regular">Description text</p> | ||
| ``` | ||
|
|
||
| #### SLDS Component Patterns | ||
| ```html | ||
| <!-- Card Layout --> | ||
| <article class="slds-card slds-var-m-around_medium"> | ||
| <header class="slds-card__header"> | ||
| <h2 class="slds-text-heading_small">Card Title</h2> | ||
| </header> | ||
| <div class="slds-card__body slds-card__body_inner"> | ||
| <!-- Card content --> | ||
| </div> | ||
| <footer class="slds-card__footer"> | ||
| <!-- Card actions --> | ||
| </footer> | ||
| </article> | ||
|
|
||
| <!-- Form Layout --> | ||
| <div class="slds-form slds-form_stacked"> | ||
| <div class="slds-form-element"> | ||
| <lightning-input label="Field Label" value={fieldValue}></lightning-input> | ||
| </div> | ||
| </div> | ||
| ``` | ||
|
|
||
| ### 4. Avoid Custom CSS | ||
|
|
||
| #### Use SLDS Classes | ||
| ```html | ||
| <!-- Color and theming --> | ||
| <div class="slds-theme_success slds-text-color_inverse slds-var-p-around_small"> | ||
| Success message | ||
| </div> | ||
|
|
||
| <div class="slds-theme_error slds-text-color_inverse slds-var-p-around_small"> | ||
| Error message | ||
| </div> | ||
|
|
||
| <div class="slds-theme_warning slds-text-color_inverse slds-var-p-around_small"> | ||
| Warning message | ||
| </div> | ||
| ``` | ||
|
|
||
| #### Avoid Custom CSS (Anti-Pattern) | ||
| ```css | ||
| /* Don't create custom styles that override SLDS */ | ||
| .custom-button { | ||
| background-color: red; | ||
| padding: 10px; | ||
| } | ||
|
|
||
| .my-special-layout { | ||
| display: flex; | ||
| justify-content: center; | ||
| } | ||
| ``` | ||
|
|
||
| #### When Custom CSS is Necessary | ||
| If you must use custom CSS, follow these guidelines: | ||
| - Use CSS custom properties (design tokens) when possible | ||
| - Prefix custom classes to avoid conflicts | ||
| - Never override SLDS base classes | ||
|
|
||
| ```css | ||
| /* Custom CSS example */ | ||
| .my-component-special { | ||
| border-radius: var(--lwc-borderRadiusMedium); | ||
| box-shadow: var(--lwc-shadowButton); | ||
| } | ||
| ``` | ||
|
|
||
| ### 5. Component Architecture Best Practices | ||
|
|
||
| #### Reactive Properties | ||
| ```javascript | ||
| import { LightningElement, track, api } from 'lwc'; | ||
|
|
||
| export default class MyComponent extends LightningElement { | ||
| // Use @api for public properties | ||
| @api recordId; | ||
| @api title; | ||
|
|
||
| // Use @track sparingly - prefer reactive properties | ||
| @track complexObject = {}; | ||
abbas133 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| // Simple reactive properties (no decorator needed) | ||
| name = ''; | ||
| isLoading = false; | ||
|
|
||
| // Computed properties | ||
| get displayName() { | ||
| return this.name ? `Hello, ${this.name}` : 'Hello, Guest'; | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| #### Event Handling Patterns | ||
| ```javascript | ||
| // Custom event dispatch | ||
| handleSave() { | ||
| const saveEvent = new CustomEvent('save', { | ||
| detail: { | ||
| recordData: this.recordData, | ||
| timestamp: new Date() | ||
| } | ||
| }); | ||
| this.dispatchEvent(saveEvent); | ||
| } | ||
|
|
||
| // Lightning component event handling | ||
| handleInputChange(event) { | ||
| const fieldName = event.target.name; | ||
| const fieldValue = event.target.value; | ||
|
|
||
| // For lightning-input, lightning-combobox, etc. | ||
| this[fieldName] = fieldValue; | ||
| } | ||
|
|
||
| handleRadioChange(event) { | ||
| // For lightning-radio-group | ||
| this.selectedValue = event.detail.value; | ||
| } | ||
|
|
||
| handleToggleChange(event) { | ||
| // For lightning-input type="toggle" | ||
| this.isToggled = event.detail.checked; | ||
| } | ||
| ``` | ||
|
|
||
| ### 6. Data Handling and Wire Services | ||
|
|
||
| #### Use @wire for Data Access | ||
| ```javascript | ||
| import { getRecord } from 'lightning/uiRecordApi'; | ||
| import { getObjectInfo } from 'lightning/uiObjectInfoApi'; | ||
|
|
||
| export default class MyComponent extends LightningElement { | ||
| @api recordId; | ||
|
|
||
| @wire(getRecord, { recordId: '$recordId', fields: FIELDS }) | ||
| record; | ||
|
|
||
| @wire(getObjectInfo, { objectApiName: 'Account' }) | ||
| objectInfo; | ||
|
|
||
| get recordData() { | ||
| return this.record.data ? this.record.data.fields : {}; | ||
| } | ||
| } | ||
| ``` | ||
abbas133 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| ### 7. Error Handling and User Experience | ||
|
|
||
| #### Implement Proper Error Boundaries | ||
| ```javascript | ||
| import { ShowToastEvent } from 'lightning/platformShowToastEvent'; | ||
|
|
||
| export default class MyComponent extends LightningElement { | ||
| isLoading = false; | ||
| error = null; | ||
|
|
||
| async handleAsyncOperation() { | ||
| this.isLoading = true; | ||
| this.error = null; | ||
|
|
||
| try { | ||
| const result = await this.performOperation(); | ||
| this.showSuccessToast(); | ||
| } catch (error) { | ||
| this.error = error; | ||
| this.showErrorToast(error.body?.message || 'An error occurred'); | ||
| } finally { | ||
| this.isLoading = false; | ||
| } | ||
| } | ||
|
|
||
| showSuccessToast() { | ||
| const event = new ShowToastEvent({ | ||
| title: 'Success', | ||
| message: 'Operation completed successfully', | ||
| variant: 'success' | ||
| }); | ||
| this.dispatchEvent(event); | ||
| } | ||
|
|
||
| showErrorToast(message) { | ||
| const event = new ShowToastEvent({ | ||
| title: 'Error', | ||
| message: message, | ||
| variant: 'error', | ||
| mode: 'sticky' | ||
| }); | ||
| this.dispatchEvent(event); | ||
| } | ||
| } | ||
abbas133 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| ``` | ||
|
|
||
| ### 8. Performance Optimization | ||
|
|
||
| #### Conditional Rendering | ||
| ```html | ||
| <!-- Use template directives for conditional rendering --> | ||
| <template if:true={isLoading}> | ||
| <lightning-spinner alternative-text="Loading..."></lightning-spinner> | ||
| </template> | ||
|
|
||
| <template if:false={isLoading}> | ||
| <template for:each={items} for:item="item"> | ||
| <div key={item.id} class="slds-var-m-bottom_small"> | ||
| {item.name} | ||
| </div> | ||
| </template> | ||
| </template> | ||
|
|
||
| <template if:true={error}> | ||
| <div class="slds-theme_error slds-text-color_inverse slds-var-p-around_small"> | ||
| {error.message} | ||
| </div> | ||
| </template> | ||
abbas133 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| ``` | ||
|
|
||
| ### 9. Accessibility Best Practices | ||
|
|
||
| #### Use Proper ARIA Labels and Semantic HTML | ||
| ```html | ||
| <!-- Use semantic structure --> | ||
| <section aria-label="Product Selection"> | ||
| <h2 class="slds-text-heading_medium">Products</h2> | ||
|
|
||
| <lightning-input | ||
| type="search" | ||
| label="Search Products" | ||
| placeholder="Enter product name..." | ||
| aria-describedby="search-help"> | ||
| </lightning-input> | ||
|
|
||
| <div id="search-help" class="slds-assistive-text"> | ||
| Type to filter the product list | ||
| </div> | ||
| </section> | ||
| ``` | ||
|
|
||
| ## Common Anti-Patterns to Avoid | ||
| - **Direct DOM Manipulation**: Never use `document.querySelector()` or similar | ||
| - **jQuery or External Libraries**: Avoid non-Lightning compatible libraries | ||
| - **Inline Styles**: Use SLDS classes instead of `style` attributes | ||
| - **Global CSS**: All styles should be scoped to the component | ||
| - **Hardcoded Values**: Use custom labels, custom metadata, or constants | ||
| - **Imperative API Calls**: Prefer `@wire` over imperative `import` calls when possible | ||
| - **Memory Leaks**: Always clean up event listeners in `disconnectedCallback()` | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.