[SalesForce] LWC pass date to @wire apex – how to initialise date variable

I have a component that on first load should display all accounts where a last verified date is 2 years or older.

The component has a date selection field where the user can select a different date, and on doing so the component should redisplay the grid with the refreshed SOQL results using the new date.

The accounts are selected via @wire call to an Apex controller which has a parameter to receive the date. If the parameter is null it calculates today's date – 2 years in the controller, but if a valid date is passed, it should take that date.

I cannot get it to work to send through a date on initial load. I can't seem to figure out how to initialise the date variable in the .js file so that on first load it works. I've tried multiple ways to get it to work but am needing help as none of them work.

Once I can get that to work, then I can get to testing whether my refresh to work, because I still haven't managed to test that yet.

My HTML:

<template>
  <template if:true={haveresults}></template>
  <lightning-card>
    <div class="slds-box slds-var-m-around_medium ">
      <div class="slds-var-m-around_medium slds-text-heading_small slds-grid slds-gutters">
        <div class="slds-col slds-size_1-of-3">
          <lightning-input type="date" name="beforedate" label="Last Verified Before Date" onchange={handleInputDate} value={date}></lightning-input>
        </div>
        <div class="slds-col slds-size_1-of-3">
            <lightning-button
            variant="brand"
            label="Refresh account list"
            title="Refresh the list of accounts"
            onclick={refreshList}
            class="slds-var-m-around_medium slds-align_absolute-center"
          ></lightning-button>
        </div>
      </div>
    </div>
    <div class="slds-box slds-var-m-around_medium slds-form-element__control slds-var-m-around_small">
      <lightning-datatable
        key-field="Id"
        data={accounts}
        columns={columns}
        sorted-by={sortBy} 
        sorted-direction={sortDir}
        onsort={updateSort}
        onrowselection={getSelectedRecord}
        >
      </lightning-datatable>
    </div>
  </lightning-card>
</template></template>

My JS below. I've tried setting the fiels inputDate to date ie running the date get call, but it doesn't work. Temporarily I've set the @wire(getAccountsToVerify, { inputdate: null }) to null just to get the html to display something, because if I set it to inputDate it doesn't work:

import { LightningElement, wire, track, api } from "lwc";
import getAccountsToVerify from "@salesforce/apex/accountController.getAccountsToVerify";
import { ShowToastEvent } from "lightning/platformShowToastEvent";
import { refreshApex } from "@salesforce/apex";

const columns = [
  {
    label: "Name",
    fieldName: "nameUrl",
    type: "url",
    typeAttributes: { label: { fieldName: "Name" }, target: "_blank" }
  },
  {
    label: "Verification Date",
    fieldName: "Verification_Date__c",
    sortable: true
  },
  {
    label: "Verification Outcome",
    fieldName: "Outcome__c"
  }
];

export default class accountVerification extends LightningElement() {
  @track error;
  @track accounts;
  @track wiredAccounts;
  @track columns = columns;
  @track resultcount;
  @track haveresults = false;
  @track inputDate;

  get date() {
    // Get the current date/time
    let rightNow = new Date();
    console.log(rightNow);
    //subtract 2 years
    rightNow.setFullYear(rightNow.getFullYear() - 2);
    console.log(rightNow);
    // Return the date in 'YYYY-MM-DD' format
    let yyyyMmDd = rightNow.toISOString().slice(0, 10);
    console.log(yyyyMmDd);
    return yyyyMmDd;
  }

  @wire(getAccountsToVerify, { inputdate: null }) //If I put inputDate in here, it is always *undefined* initially! HELP!
  accountResult(result) {
    this.wiredAccounts = result;
    if (result.data) {
      this.accounts = result.data.map((record) =>
        Object.assign({ nameUrl: "/" + record.Id }, record)
      );
      //this.data = data;
      this.resultcount = this.accounts.length;
      if (this.resultcount > 0) {
        this.haveresults = true;
      } else {
        this.haveresults = false;
      }
      this.error = undefined;
    } else if (result.error) {
      this.error = error;
      this.accounts = undefined;
    }
  }

  refreshList() {
    console.log(this.inputDate);
    if (this.inputDate == null) {
      this.dispatchEvent(
        new ShowToastEvent({
          title: "Refresh grid",
          message: "You have not set a date to refresh the grid contents with",
          variant: "error"
        })
      );
    } else {
      return refreshApex(this.wiredAccounts);
    }
  }

  getSelectedRecord(event) {
    this.selectedRecords = event.detail.selectedRows;
  }


  handleInputDate(event) {
    this.inputDate = event.target.value;
  }
}

And my Apex:

@AuraEnabled(cacheable=true)
public static List<Account> getAccountsToVerify(string inputdate) {
  DateTime beforeDate = inputdate == null
    ? System.now().addYears(-2)
    : DateTime.parse(inputdate);
  return [
    SELECT Id, Name, Outcome__c, Verification_Date__c
      FROM Account WHERE
      isPersonAccount = TRUE
      AND (Verification_Date__c = NULL
      OR Verification_Date__c < :beforeDate)
    ORDER BY Name
  ];
}

Best Answer

Wire methods don't fire on "undefined". You need to make it null instead:

inputDate = null;

Or, alternatively, set a specific date:

inputDate = new Date(new Date().setFullYear(new Date().getFullYear() - 2));

Note that the values you get are real dates, you don't need to Date.parse:

@AuraEnabled(cacheable=true)
public static List<Account> getAccountsToVerify(Date inputdate) {
  return [
    SELECT Id, Name, Outcome__c, Verification_Date__c
      FROM Account WHERE
      isPersonAccount = TRUE
      AND (Verification_Date__c = NULL
      OR Verification_Date__c < :inputdate)
    ORDER BY Name
  ];
}

Edit: I packaged this up for you, if you want a copy to work with.

Related Topic