What you will learn
- How to use refresh apex
- Creating multi column layout
- Get current date and time in LWC
- Use lightnitg-input as date
- How to use different toast messages with different variants
- Get records from apex and show in lwc
- Update picklist value from LWC to apex
Watch Demo
Code Files
HTML
<!-- Show left bat where we can add todo's and on write side show all todos along with todos we have added from laft side.
The todos we have on right wide will have cosss button on cliking it doto will get deleted from right side but it will be present in backend with staus done -->
<template>
<div class="slds-grid slds-gutters slds-wrap slds-theme_shade slds-p-around_xx-small">
<!-- Left Section (30%) -->
<div class="slds-col slds-size_1-of-1 slds-medium-size_1-of-3">
<div class="slds-box slds-theme_default">
<lightning-input
type="text"
label="Name"
placeholder="Max length 80"
value={newTodoTitle}
onchange={handleTitleChange}>
</lightning-input>
<lightning-combobox
name="priority"
label="Priority"
value={selectedPriority}
placeholder="priority"
options={priorityOptions}
onchange={handlePriorityChange} >
</lightning-combobox>
<lightning-input
type="datetime"
label="Due Date"
value={defaultDate}
onchange={handleDateChange}>
</lightning-input>
<lightning-button
label="Add To-Do"
variant="brand"
class="slds-m-top_medium slds-align_absolute-center"
onclick={addTodo}>
</lightning-button>
</div>
</div>
<div class="slds-col slds-size_1-of-1 slds-medium-size_2-of-3">
<div class="slds-grid slds-wrap slds-gutters">
<template if:true={todos}>
<template for:each={todos} for:item="todo">
<div key={todo.Id} class="slds-col slds-size_1-of-1 slds-medium-size_1-of-3 slds-p-bottom_small">
<div class="slds-card slds-card_boundary" style="position: relative;">
<!-- Close Icon in Top-Right -->
<lightning-button-icon
icon-name="utility:close"
alternative-text="Mark as Done"
onclick={markAsDone}
data-id={todo.Id}
class="slds-is-absolute"
style="top: 0.5rem; right: 0.5rem;">
</lightning-button-icon>
<div class="slds-card__header">
<h2><b>{todo.Name}</b></h2>
</div>
<div class="slds-card__header">
<p><b>Priority</b>: {todo.cbugs__Priority__c}</p>
<p><b>Due On</b>: {todo.cbugs__Due_Date__c}</p>
</div>
</div>
</div>
</template>
</template>
<template if:false={todos}>
<p class="slds-text-body_regular slds-p-around_medium slds-text-align_center">
No To-Do items found!
</p>
</template>
</div>
</div>
</div>
</template>
JavaScript
import { LightningElement, track, wire } from 'lwc';
import getTodos from '@salesforce/apex/TodoController2.getTodos';
import addTodo from '@salesforce/apex/TodoController2.addTodo';
import markTodoAsDone from '@salesforce/apex/TodoController2.markTodoAsDone';
import { refreshApex } from '@salesforce/apex';
import { ShowToastEvent } from "lightning/platformShowToastEvent";
export default class TodoBoard2 extends LightningElement {
@track todos = [];
newTodoTitle = '';
@track wiredAccountResult;
@track selectedDateTime;
selectedPriority = 'Medium'
get priorityOptions() {
return [
{ label: 'Low', value: 'Low' },
{ label: 'Medium', value: 'Medium' },
{ label: 'High', value: 'High' },
];
}
@track defaultDate;
@wire (getTodos) wiredTodos(result){
this.wiredAccountResult = result;
if (result.data) {
this.todos = result.data;
} else if (result.error) {
console.log(result.error);
}
}
// Not working for refresh apex. why?
// @wire(getTodos)
// wiredTodos({ error, data }) {
// this.wiredRecords = data;
// if (data) {
// this.todos = data;
// } else if (error) {
// console.error('Error fetching todos:', error);
// }
// }
connectedCallback() {
this.defaultDate = this.defaultDateCalculator();
}
handleTitleChange(event) {
this.newTodoTitle = event.target.value;
}
addTodo() {
if (this.newTodoTitle.trim() === '') {
this.showToast('Warning','Name is requierd', 'Warning');
return;
}
addTodo({ title: this.newTodoTitle, dueDate: this.selectedDateTime, priority: this.selectedPriority})
.then(() => {
this.setValuesToDefault();
this.showToast('Success','New To-Do Added', 'success');
this.handleRefreshView();
})
.catch(error => {
this.showToast('Error',error, 'Error');
});
}
markAsDone(event) {
const todoId = event.target.dataset.id;
markTodoAsDone({ todoId })
.then(() => {
this.showToast('Success','Congrats Great Work!!!', 'success');
this.handleRefreshView();
})
.catch(error => {
this.showToast('Warning','Error in adding To-Do.', error, 'Warning');
});
}
handleRefreshView() {
refreshApex(this.wiredAccountResult);
}
defaultDateCalculator() {
const today = new Date();
today.setDate(today.getDate() + 1); // Add 1 day to the current date
return this.selectedDateTime = today.toISOString();
}
handleDateChange(event) {
this.selectedDateTime = event.target.value;
}
handlePriorityChange(event) {
this.selectedPriority = event.target.value;
}
setValuesToDefault() {
this.newTodoTitle = '';
this.selectedPriority = 'Medium'
this.defaultDate = this.defaultDateCalculator();
}
showToast(title, message, variant) {
const evt = new ShowToastEvent({
title: title,
message: message,
variant: variant,
});
this.dispatchEvent(evt);
}
}
Apex Controller
public with sharing class TodoController2 {
@AuraEnabled(cacheable = true)
public static List<cbugs__ToDo__c> getTodos() {
List<cbugs__ToDo__c> lst = [SELECT Id, Name, cbugs__Status__c,cbugs__Due_Date__c, cbugs__Priority__c FROM cbugs__ToDo__c WHERE cbugs__Status__c != 'Completed' and cbugs__Status__c != 'Backlog'];
return lst;
}
@AuraEnabled
public static void addTodo(String title, DateTime dueDate, String priority) {
cbugs__ToDo__c newTodo = new cbugs__ToDo__c();
newTodo.Name = title;
newTodo.cbugs__Status__c = 'New';
newTodo.cbugs__Due_By__c = dueDate;
newTodo.cbugs__Priority__c = priority;
insert newTodo;
}
@AuraEnabled
public static void markTodoAsDone(Id todoId) {
cbugs__ToDo__c todo = [SELECT Id, cbugs__Status__c FROM cbugs__ToDo__c WHERE Id = :todoId LIMIT 1];
todo.cbugs__Status__c = 'Completed';
update todo;
}
}