Sunday, 27 June 2021

Parse CSV file using Lightning Web Component(LWC)

Use case:

Need an functionality to import CSV file and parse  those records for further processing. This post will explain how to use LWC component to process CSV in client side without using apex code.

Hope you are going to like this post.

Lets get through the Code :

app.html


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<!--
 * @File Name          : app.html
 * @Description        : 
 * @Author             : Swarup Satpati
 * @Last Modified By   : Swarup Satpati
 * @Last Modified On   : 6/25/2020, 4:57:24 PM
 * @Modification Log   : 
 * Ver       Date            Author            Modification
 * 1.0    6/25/2020      Swarup Satpati     Initial Version
-->

<template>
<lightning-card title="CSV Uploader" icon-name="custom:custom19">
<form class="slds-form--inline">
<div class="slds-form-element">
    <lightning-input type="file"
                     label="Choose File"
                     accept=".csv"
                     onchange={importcsv}
                     multiple>
    </lightning-input>
</div>  

<div class="slds-form-element slds-text-body_small slds-text-color_error">{filename}</div>

<div class="slds-form-element">
    <lightning-button label="Import" title="Non-primary action" onclick={readFiles} class="slds-m-left_x-small"></lightning-button>
</div>

<div style="margin-left:4%" class="slds-form-element">
<template if:true={showLoadingSpinner}>
        <lightning-spinner alternative-text="Uploading......" size="medium"></lightning-spinner>
    </template>
</div>

</form>

<br/>
    <lightning-datatable
            data={data}
            columns={columns}
            key-field="SAID"
        >
    </lightning-datatable>
</lightning-card> 
</template>


app.js


  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
/**
 * @File Name          : app.js
 * @Description        : 
 * @Author             : Swarup Satpati
 * @Last Modified By   : Swarup Satpati
 * @Last Modified On   : 6/25/2020, 4:57:24 PM
 * @Modification Log   : 
 * Ver       Date            Author            Modification
 * 1.0    6/25/2020      Swarup Satpati     Initial Version
**/
import { LightningElement, track, api } from 'lwc';

const COLS = [
    { label: 'SA ID', fieldName: 'SAID' },
    { label: 'UUID', fieldName: 'UUID'}
];
export default class App extends LightningElement {
    @track columns = COLS;
    @track data;
    @track showLoadingSpinner = false;

    MAX_FILE_SIZE = 2000000; //Max file size 2.0 MB
    filesUploaded = [];
    filename;
 
    importcsv(event){
        if (event.target.files.length > 0) {
            this.filesUploaded = event.target.files;
            this.filename = event.target.files[0].name;
            console.log(this.filename);
            if (this.filesUploaded.size > this.MAX_FILE_SIZE) {
                this.filename = 'File Size is to long to process';
            } 
    }
    }
    readFiles() {
        [...this.template
            .querySelector('lightning-input')
            .files].forEach(async file => {
                try {
                    const result = await this.load(file);
                    // Process the CSV here
                  this.showLoadingSpinner = false;

                    console.log(result);
                   // this.processData(result);
                     this.data=JSON.parse(this.csvJSON(result));
                    console.log('data..'+JSON.parse(this.data));

                } catch(e) {
                    // handle file load exception
                    console.log('exception....');
                }
            });
    }
    async load(file) {
        return new Promise((resolve, reject) => {
        this.showLoadingSpinner = true;
            const reader = new FileReader();
            // Read file into memory as UTF-8      
            //reader.readAsText(file);
            reader.onload = function() {
                resolve(reader.result);
            };
            reader.onerror = function() {
                reject(reader.error);
            };
            reader.readAsText(file);
        });
    }

     
//process CSV input to JSON
 
 csvJSON(csv){

  var lines=csv.split(/\r\n|\n/);

  var result = [];

  var headers=lines[0].split(",");
  console.log('headers..'+JSON.stringify(headers));
  for(var i=1;i<lines.length-1;i++){

   var obj = {};
   var currentline=lines[i].split(",");

   for(var j=0;j<headers.length;j++){
    obj[headers[j]] = currentline[j];
   }

   result.push(obj);

  }
  console.log('result..'+JSON.stringify(result));
  //return result; //JavaScript object
  return JSON.stringify(result); //JSON
}

}


Explanation:

Have created a CSV with two columns SAID,UUID and prepare almost 4k records for demo purpose.  After uploading this CSV once we click on import button component  is  invoking a method  to pass this file to fileReader  and in-turn it's invoke another method to parse this file-reader object into JSON format. Finally , we are displaying json data in lightning data table for further processing....... !.

Note: for big file we should be careful to utilize this approach but its work perfectly till 2 mb.


Output:





Thursday, 18 March 2021

Custom Multi select dropdown using LWC

Recently i have worked on " multi select picklist" component required for my project. Showing you how to create it using LWC and hopefully you can use this component as your need.

it looks great and work beautifully , Lets enjoy ..!


multiselectdropdown.html


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<template>
    <div class="slds-form-element">
     <label class="slds-form-element__label" for="combobox-id-5">Relate to</label>
        <div class="slds-form-element__control">
          <div class="slds-combobox_container slds-size_small">
            <section id="maindiv" class="slds-combobox slds-dropdown-trigger slds-dropdown-trigger_click slds-is-open" aria-expanded="true" aria-haspopup="listbox" role="combobox">
              <div onclick={handleClick} onmouseleave={handleMouseOut} class="slds-combobox__form-element slds-input-has-icon slds-input-has-icon_right" role="none">
                <input type="text" class="slds-input slds-combobox__input slds-has-focus slds-combobox__input-value" id="combobox-id-5" aria-controls="listbox-id-5"  role="textbox" placeholder={defaultText} readonly=""
                />
            
                <span class="slds-icon_container slds-icon-utility-down slds-input__icon slds-input__icon_right">
                    <lightning-icon icon-name="utility:down" size="x-small" alternative-text="Approved"></lightning-icon>
                </span>
              </div>
              <template if:true={iswindowOpen}>
              <div onmouseenter={handlemouseOver} onmouseleave={handleMouseLeave} id="listbox-id-5" class="slds-dropdown slds-dropdown_length-5 slds-dropdown_fluid" role="listbox">
                <ul class="slds-listbox slds-listbox_vertical" role="presentation">
                <template for:each={_options} for:item="option">
                    <c-list-items key={option.value}
                                         value={option.value}
                                         label={option.label}
                                         selected={option.selected}
                                         onselected={handleSelectedClick}></c-list-items>
                    
                  </template>
                  </ul>
              </div>
            </template>

            </section>
          </div>
        </div>
      </div>
</template>



multiselectdropdown.js



  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
import { LightningElement, api, track } from 'lwc';

export default class Multiselectdropdown extends LightningElement {
@api options = [{label:'Resource 1',value:'Resource 1',selected:false},
    {label:'Resource 2',value:'Resource 2',selected:false},
    {label:'Resource 3',value:'Resource 3',selected:false},
    {label:'Resource 4',value:'Resource 4',selected:false},
    {label:'Resource 5',value:'Resource 5',selected:false},
    {label:'Resource 6',value:'Resource 6',selected:false},
    {label:'Resource 7',value:'Resource 7',selected:false},
    {label:'Resource 8',value:'Resource 8',selected:false}];
    @api selectedValues=[];
    @api label=' ';
    @track _options= [];
    @track iswindowOpen=false;

  /*Init() call..*/
    connectedCallback() {
        this._options = JSON.parse(JSON.stringify(this.options));
        //sort all array items befor display it to ui
        this._options=this._options.sort(function compare(a,b) {
            if (a.value == 'All'){
              return -1;
            }
            else if (a.value < b.value){
              return -1;
            }
            if (a.value > b.value){
              return 1;
            }
            return 0;
          });
        
      }
      get defaultText(){
        if (this.selectedValues.length === 0) {
          return "Select an option...";
        }
        if (this.selectedValues.length === 1) {
          return this.selectedValues[0].label;
        }
        else{
          return this.selectedValues.length+" Options Selected";

        }
      }

      handleClick(event){
          console.log('query selector..'+this.template.querySelector("section"));
        this.iswindowOpen=true;
        this.template.querySelector("section").classList.add("slds-is-open");
      }

      handleMouseOut(event){
       if(this.iswindowOpen){
        return;
       }
       this.template.querySelector("section").classList.remove("slds-is-open");
      }

      handleMouseLeave(event){
        this.iswindowOpen=false;
        this.template.querySelector("section").classList.remove("slds-is-open");

      }

      handlemouseOver(event){
        this.iswindowOpen=true;
      }

      handleSelectedClick(event){

        var value;
        var selected;
        event.preventDefault();
        event.stopPropagation();
    
        const data = event.detail;
    
        value = data.value;
        selected = data.selected;
    
        //shift key ADDS to the list (unless clicking on a previously selected item)
        //also, shift key does not close the dropdown.
        if (data.shift) {
          this._options.forEach(function(option) {
            if (option.value === value) {
              option.selected = selected === true ? false : true;
            }
          });
        }
        else {
          this._options.forEach(function(option) {
            if (option.value === value) {
              option.selected = selected === "true" ? false : true;
            } else {
              option.selected = false;
            }
          });
         // this.closeDropdown();
        }
    
        this.selectedValues = this.getOptionsArray();
    
      }

      getOptionsArray(){
        var pills = [];
        this._options.forEach(function(element) {
          var interator = 0;
          if (element.selected) {
            pills.push({label:element.label, name:element.value, key: interator++});
          }
        });
        return pills;
      }
    

}


Child Component :

listItems.html



 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
<template>
    <li onclick={eventHandler} class="slds-listbox__item" role="presentation"  >
        <div class={listStyle} role="option">
          <span class="slds-media__figure">
            <lightning-icon icon-name="utility:check" size="x-small" alternative-text="selected" class="slds-icon-utility-check slds-current-color slds-listbox__icon-selected slds-icon_container"></lightning-icon>
          </span>
          <span class="slds-media__body">
            <span class="slds-truncate no-selection" title={label}>&nbsp;{label}</span>
          </span>
        </div>
      </li>
</template>

listItems.js



 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
import { LightningElement,api,track } from 'lwc';

export default class ListItems extends LightningElement {

  @api key = '';
  @api value = '';
  @api label = '';
  @api selected = false;

  get listStyle() {
    var initial = ' slds-media  slds-listbox__option_plain slds-media_small slds-listbox__option ';
    return this.selected === true ? initial + ' slds-is-selected ' : initial ;
  }

  eventHandler(event) {
    event.preventDefault();
    event.stopPropagation();
    console.log('selcted value..'+this.selected);
    const selectedEvent = new CustomEvent('selected', { detail: {label:this.label,value:this.value,selected:this.selected,shift:event.shiftKey} });
    this.dispatchEvent(selectedEvent);
  }
}

Explanation..

in code we are using Shift key to select multiple options from dropdown. on select option(s) , events is getting fired from child component and being handled on parent component 
handleSelectedClick(event)

one tricky part is handling showing and hiding of drop down list using below two events:
  • onmouseenter
  • onmouseleave

OutPut :

Lets see the output and hope you will like it.

Wednesday, 30 September 2020

ESlint in LWC

 Before we jump into "ESlint" let me explain about "linter"

what is linter ?

A linter is a tool that identifies issues in your code. Running a linter against your code can tell you many things:

  • if the code adheres to a certain set of syntax conventions
  • if the code contains possible sources of problems
  • if the code matches a set of standards you or your team define

It will raise warnings that you, or your tools, can analyze and give you actionable data to improve your code. ESLint is basically a linter for the JavaScript programming language, written in Node.js

ESlint for LWC

In salesforce ESlint is available by default with the Lightning Web Components extension .Salesforce provides specific ESLint rules out of the box for you as a Lightning Web Component developer so that you can write great code. And if you make a mistake, the linting rules help you see it before you deploy your code.

probably you may remember when create a new project, in lwc metadata folder there is file called ".eslintrc" which define the salesforce specific linting rules.




you may have experienced with the Restricted async operation 'setTimeOut' in LWC. lets take a look into below code snippet which is restricted by ESlint due to performance impact.

 
1
2
3
4
5
connectedCallback() {
   setTimeout(() => {
       this.variable = true;
   }, 3000);
} 


The ESLint for Lightning Web Components will complain about setTimeout and setInterval. if you wanted to use it for any reason you can stop this by adding a comment before the line of code .

 
1
2
3
4
5
6
// eslint-disable-next-line @lwc/lwc/no-async-operation
connectedCallback() {
   setTimeout(() => {
       this.variable = true;
   }, 3000);
} 


Hope you find this post informative ..



Monday, 31 August 2020

Dynamically bind variable in Lightning Web Component (LWC)

 Use case

Once we will be working with generic component we may have to bind declared variables  dynamically in code to get expected result .

Based on below example we  can display  account name for an particular 'accountId' 

import { LightningElement, wire } from 'lwc';
import { getRecord, getFieldValue } from 'lightning/uiRecordApi';
import NAME_FIELD from '@salesforce/schema/Account.Name';

export default class Example extends LightningElement {
    @wire(getRecord, { recordId: '0013xx065790ASZ', fields: [NAME_FIELD] })
    account;

     get name() {
        return getFieldValue(this.account.data, NAME_FIELD);
    }

 
    
}

 

Instead of importing the field definition in controller we can dynamically pass  fields array  within getrecord().


Lets have a look into the code.

Controller

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
/**
 * @File Name          : dynamicbinding.js
 * @Description        : 
 * @Author             : Swarup Satpti
 * @Group              : 
 * @Last Modified By   : Swarup Satpati
 * @Last Modified On   : 8/31/2020, 5:00:00 PM
**/
import { LightningElement, api, wire, track } from 'lwc';
import { getFieldValue } from 'lightning/uiRecordApi';
import {getRecord} from 'lightning/uiRecordApi';

export default class Chevron extends LightningElement {
    @api objectName = 'Account';
    @api fieldName = 'Name';
    
    /*component with a recordId property is used on a Lightning record page, 
    the page sets the property to the ID of the current record.*/
    @api recordId='001W000000dls6ZIAQ'; 
    @track record;
    @track error;
    @track fieldArray;
    @track fieldValue;


    connectedCallback(){
        console.log("hi..");
        this.fieldArray = [`${this.objectName}.${this.fieldName}`,`${this.objectName}.RecordTypeId`];
    }
    
    /*Use this wire adapter to get a record’s data : 
       Recordtype ID and value of status field pass through API
    */
    @wire(getRecord, { recordId: '$recordId', fields:'$fieldArray'})
    wiredAccount({ error, data }) {
        if (data) {
            this.record = data;
            console.log(JSON.stringify(data));
           // this.fieldvalue=getFieldValue(data,`${this.objectName}.${this.fieldName}`);
            this.error = undefined;
        } else if (error) {
            console.log('error..');

            this.error = error;
            this.record = undefined;
        }
    }

    get name() {
        return getFieldValue(this.record,`${this.objectName}.${this.fieldName}`);
    }
}

  HTML Template

1
2
3
4
5
<template>
    <div class="slds-m-around_medium">
        <p>Account Name: {name}</p>
    </div>
</template>


Code Explanation:

within Js controller variables are dynamically bound using '$' sign as below.

  this.fieldArray = [`${this.objectName}.${this.fieldName}`,`${this.objectName}.RecordTypeId`]

 Finally  Code will return the  value of account name for given account ID .


Hope you got it useful....! cheers ..

Wednesday, 5 August 2020

Custom Chevron component using lightning web component(LWC)

Use case :

we can use sales force standard "Path" component to build chevron on record page showed as below.


                                                                                                                                                                           
But there is an problem 😟   with this approach . As you can see once stage is completed it shows the chevron with right check mark and not displaying the status  and also i don't want user to manually change the status by using "Mark Stage Completed"  button on  right which should not be available to end user.

To achieve this we have to use custom LWC component. Let's get into the code..!

Code:

Chevron.js

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
/**
 * @File Name          : chevron.js
 * @Description        : 
 * @Author             : Swarup Satpti
 * @Group              : 
 * @Last Modified By   : Swarup satpati
 * @Last Modified On   : 8/3/2020, 5:30:00 PM
**/
import { LightningElement, api, wire, track } from 'lwc';
import { getObjectInfo, getPicklistValues} from 'lightning/uiObjectInfoApi';
import { getFieldValue } from 'lightning/uiRecordApi';
import {getRecord} from 'lightning/uiRecordApi';

export default class Chevron extends LightningElement {
    @api objectName = 'Opportunity';
    @api fieldName = 'StageName';
    /*component with a recordId property is used on a Lightning record page, 
    the page sets the property to the ID of the current record.*/
    @api recordId; 

    @track picklistvalues;
    @track record;
    @track error;
    @track chevrondata=[];
    @track itemList;
    @track fieldValue;
    @track fieldArray;

    recordtypeId;
    index=0;
    isFound=false;
    isfoundindex=0;
    fieldapi;


  connectedCallback(){
    this.fieldArray = [`${this.objectName}.${this.fieldName}`,`${this.objectName}.RecordTypeId`];
    this.fieldapi=`${this.objectName}.${this.fieldName}` ;
    }
    
    /*Use this wire adapter to get a record’s data : 
       Recordtype ID and value of status field pass through API
    */
    @wire(getRecord, { recordId: '$recordId', fields:'$fieldArray'})
    wiredAccount({ error, data }) {
        if (data) {
            this.record = data;
            console.log(JSON.stringify(data));
            this.fieldvalue=getFieldValue(data,`${this.objectName}.${this.fieldName}`);
            this.recordtypeId=this.record.fields.RecordTypeId.value;
            this.error = undefined;
            console.log('selected value..'+this.fieldvalue);
        } else if (error) {
            console.log('error..');

            this.error = error;
            this.record = undefined;
        }
    }

   /*Use this wire adapter to get the picklist values for a specified field.*/

    @wire(getPicklistValues, {
        fieldApiName: '$fieldapi',
        recordTypeId: '$recordtypeId'
    })
    fetchRecordTypeInfo({ data, error }) {
        if (data) {
            console.log('data..'+JSON.stringify(data.values));

           // this.picklistvalues = data.picklistFieldValues.Status_EI__c.values;
              this.picklistvalues = data.values ;

            this.picklistvalues.forEach(item=>{
               // console.log('rec..'+item.value);
                let classType;
                if(this.fieldvalue==item.value){
                    classType = 'slds-path__item slds-is-current slds-is-active';
                    this.isFound=true;
                    this.isfoundindex=this.index;
                }
                else{ 
                   classType='slds-path__item slds-is-incomplete';
                   this.index ++; 
                }
                this.chevrondata.push({
                 stages :item,
                 classType:classType
                });


            });
            if(this.isFound){
                for(let i=0;i<this.isfoundindex;i++){
                   this.chevrondata[i].classType='slds-path__item slds-is-complete';
                }

            }
           
             console.log('chevron data..'+JSON.stringify(this.chevrondata));
           
            //console.log(JSON.stringify(this.picklistvalues));
        }
        else if (error) {
            console.log(" Error  ---> " + JSON.stringify(error));
        }
    }
    
}

chevron.html

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<template>
    <div class="slds-path">
        <div class="slds-grid slds-path__track">
          <div class="slds-grid slds-path__scroller-container">
            <div class="slds-path__scroller" role="application">
              <div class="slds-path__scroller_inner">
                <ul class="slds-path__nav" role="listbox" aria-orientation="horizontal">
                  <template for:each={chevrondata} for:item="stageIs" for:index="index">
                    <li key={stageIs} class={stageIs.classType} style="margin-left: 0em !important;" role="presentation">
                        <a aria-selected="flase" class="slds-path__link" href="javascript:void(0);"  role="option" tabindex="0">
                          <span class="slds-path__stage">
                            <!--<svg class="slds-icon slds-icon_x-small" aria-hidden="true">
                              <use xlink:href="/assets/icons/utility-sprite/svg/symbols.svg#check"></use>
                            </svg>
                          -->
                           {stageIs.stages.label}
                            <span class="slds-assistive-text">{stageIs.stages.label}</span>
                          </span>
                          <span class="slds-path__title">{stageIs.stages.label}</span>
                        </a>
                    </li>
                  </template>
                </ul>
            </div>
          </div>
        </div>
        </div>
    </div>
</template>

Metadata

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>48.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__AppPage</target>
        <target>lightning__RecordPage</target>
        <target>lightning__HomePage</target>
        <target>lightningCommunity__Page</target>
        <target>lightning__Tab</target>
    </targets>
</LightningComponentBundle>


Code Explanation:

Within js controller we are using two wire adapters.

getRecord() : by using this method we are  retrieving the present stage value and record type Id for  the current record

getPicklistValues() : dynamically fetching pick list values for the given field Api 
and recordtype.

Have created custom property called 'ClassType' and 'stage' to display 
the chevron in html.

Main tricky part is to set the claastype conditionally based on the current stage.

'slds-path__item slds-is-current slds-is-active' :   for current Stage
'slds-path__item slds-is-incomplete': for all incomplete stages
'slds-path__item slds-is-complete' : for all completed stages


Hope you get it right !

Output :



Wednesday, 11 March 2020

Record Type Selection in LWC and Open New object page


In lightning web component(LWC) we don't need to call server to retrieve record type details. There is a native adapter available to retrieve object specific record types .
we have to use the wire adapter getObjectInfo to get the metadata about a specific object. As part of successful response it returns describing fields, child relationships, record type,etc.

In this example, we are using Account Object where i have overridden the new button using lightning component and in turns it's invoking LWC component  to display all record types .


let see the output..














on click Next button we are calling "handlechange" function to fetch selected record id and passing it to <lightning-record-form> to open new standard Account page for selected record type.










RecordtypePoc.html

<template>
    <div if:true={openmodel}>
        <template if:true={objectInfo.data}>
            <div role="dialog" tabindex="-1" aria-labelledby="header43" class="slds-modal slds-fade-in-open">
                <div class="slds-modal__container">
                    <div class="slds-modal__header">
                        <button class="slds-button slds-modal__close slds-button--icon-inverse" title="Close" onclick={closeModal}>
                            X<span class="slds-assistive-text">Cancel</span>
                        </button>
                        <h2 id="header43" class="slds-text-heading--medium">New Account</h2>
                    </div>
                    
                    <div class="slds-modal__content slds-p-around--medium">
                        <div class="slds-grid slds-wrap">
                            <div class="slds-size--1-of-2 slds-large-size--1-of-2">
                                <div class="slds-align--absolute-center">Select a Record Type</div>                            
                           </div>
                            <div class="slds-size--1-of-2 slds-large-size--1-of-2">
                                <lightning-combobox name="recordType" label="" placeholder="Choose Account record type"
                                    value={value} options={recordTypeId} onchange={changeHandler}>
                                </lightning-combobox>
                            </div>&nbsp; &nbsp;
                        </div>                   
                    </div>
                    <div class="slds-modal__footer">
                        <lightning:button class="slds-button slds-button--neutral" >Cancel</lightning:button>
                        <lightning:button class="slds-button slds-button--brand" onclick={handleChange}>Next</lightning:button>
                    </div>
                </div>
                </div>
                <div class="slds-backdrop slds-backdrop--open"></div>
            
        </template>
    </div>
        <template  if:true={recordTypeIdVal}> 
            
        <lightning-record-form
            object-api-name="Account"
            record-type-id={recordTypeIdVal}
            fields={fields}
            onsuccess={handleSuccess}>
    </lightning-record-form>
        </template>
</template>


recordtypePoc.js 


import { LightningElement, api, wire, track } from 'lwc';
import { getObjectInfo } from 'lightning/uiObjectInfoApi';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
import ACCOUNT_OBJECT from '@salesforce/schema/Account';
import NAME_FIELD from '@salesforce/schema/Account.Name';
import REVENUE_FIELD from '@salesforce/schema/Account.AnnualRevenue';
import INDUSTRY_FIELD from '@salesforce/schema/Account.Industry';

export default class RecordFormWithRecordType extends LightningElement {
// ApI name for App Builder setup
    @api recordId;
    @api objectApiName;
    @api optionVal;

    @track objectInfo;
    @track recordTypeIdVal;
    @track openmodel = true;
 
    fields = [NAME_FIELD, REVENUE_FIELD, INDUSTRY_FIELD];
    @wire(getObjectInfo, { objectApiName: ACCOUNT_OBJECT })
    objectInfo;
    get recordTypeId() {
     
    // Returns a map of record type Ids
     
       var recordtypeinfo = this.objectInfo.data.recordTypeInfos;
       var uiCombobox = [];
   
      console.log("recordtype" + recordtypeinfo);
      for(var eachRecordtype in  recordtypeinfo)//this is to match structure of lightning combo box
      {
        if(recordtypeinfo.hasOwnProperty(eachRecordtype))
        uiCombobox.push({ label: recordtypeinfo[eachRecordtype].name, value: recordtypeinfo[eachRecordtype].name })
      }
      //console.log('uiCombobox' + JSON.stringify(uiCombobox));
      return uiCombobox;
    }
    changeHandler(event){
        this.optionVal=event.target.value;
    }
    handleChange(event) {
         // Returns a map of record type Ids
         const rtis = this.objectInfo.data.recordTypeInfos;
         this.recordTypeIdVal=(Object.keys(rtis).find(rti => rtis[rti].name === this.optionVal));
         this.closeModal();
        }

        handleSuccess(event) {
            const evt = new ShowToastEvent({
                title: "Account created",
                message: "Record ID: " + event.detail.id,
                variant: "success"
            });
            this.dispatchEvent(evt);
        }
        openModal() {
            this.openmodel = true
        }
        closeModal() {
            this.openmodel = false
        }

    }

recordtypePoc.js-meta.xml


<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>47.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
      <target>lightning__AppPage</target>
      <target>lightning__RecordPage</target>
      <target>lightning__HomePage</target>
    </targets>

</LightningComponentBundle>

Getting started with Heroku

I am familiar with the heroku for quite long time, have seen lots of people are interested with it but not sure from where its need to Start...