Reference - Git commands

Version control systems allow you to track all changes made to your codebase and enables you to do things like reverting to an old version of code, developing features separately without affecting other people's changes etc. There are many version control tools like Git, SVN/subversion etc. Git is a very popular version control system out there. It is a distributed version control system, ie - every user will have their own seprate copy of code and can continue development even if there is no connectivity to server. From Salesforce development perspective, using version control systems like git became more important than earlier with Salesforce DX(SFDX).

Basics

This article assumes that you know basics of git. Once you are familiar with basics, you can use this reference article to quickly find common git commands. If you want to go through basics of git please checkout this git guide.


#GIT Basic Commands
#Creating new repo
git init [project-name]
#Cloning existing repo
git clone [url]
#List all new/modified files that needs to be committed
git status
#Shows difference in files that is not yet staged
git diff
#Add particular file for staging
git add [file]
#Add all files for staging
git add .
OR
git add -A
#Show difference between staging and latest local file
git diff --staged
#Show difference with a commit
git diff HEAD
git diff HEAD^
git diff HEAD~6
#Show difference between commits
git diff HEAD^..HEAD
git diff sha1..sha2
git diff master featureBranch
git diff --since=2.month.ago --until=1.week.ago
#Show all changes to a single file by lines with date
git blame index.html --date short
#Unstage file with preserved content
git reset [file]
#Committing file
git commit -m "Message"
#Adding and committing file in one shot
git commit -am "Message"
#List all branches
git branch
git branch -r #shows remote branches
git remote show origin #Shows more details about each local and remote branch
git remote prune origin #Cleans up deleted remote branches
#Create new branch
git branch [branch-name]
#Checking out/Switching to specific branch
git checkout [branch-name]
#Creating and Checking out a branch in one step
git checkout -b [branch-name]
#Creating a branch and checking out from a different branch
git checkout -b myfeature develop
#Merging specific branch's commits into the current branch
git merge [branch]
#Adding remote link
git remote add origin ssh://git@stash.ddhive.com:7999/test/test.git
git remote rm origin
git remote rename origin newname
#List all remotes
git remote -v
#Publishing branch to remote repo
git push -u origin [branch-name]
#Pushing tags to remote
git push <remote> --tags
#Deleting branch locally
git branch -d [branch-name] --> If changes are fully merged
git branch -D [branch-name] --> Force deleting even if changes are not fully merged
#Deleting branch from remote
git push origin --delete [branch-name]
OR
#git push origin :[branch-name]
#Delete file and stage deletion
git rm [filename]
#Remove from version control and preserve locally
git rm --cached [filename]
#Move/rename file and prepare for commit
git mv [oldname] [newname]
#Temporarily stash all modified tracked files
git stash
#Restores latest stashed files
git stash pop
#OR
git stash apply + git stash drop
#Lists all stashed changesets
git stash List
#Delete most recent stashed changeset
git stash drop
#Putting to stash and applying back
git stash save
or
git stash save "message to stash"
or
git stash save --keep-index #To stash and keep staged files as such
or
git stash save --include-untracked #To stash and keep untracked files also
git stash apply
or
git stash apply stashName
git stash branch branchName stashName # to create branch from stash
git stash show stashName # to get details of stash
git stash clear # clear all stashes
#Enabling color
git config --global color.ui true
#Listing all config
git config --list
#List version history
git log
#One line log
git log --pretty=oneline
#Log with change details
git log --oneline -p
#Log with how many lines inserted/remoted
git log --oneline --stat
#Log with graphical branching
git log --oneline --grph
#Filtering logs with time range
git log --since=2.month.ago --until=1.week.ago
#List version history in graphical manner
git log --graph
#Creating alias for log
git config --global alias.mylog "log --pretty=format:'%h %s [%an]' --graph"
git mylog
#Alias for status
git config --global alias.st status
git st
#List version history of a particular file
git log --follow [filename]
git diff [first-branch]...[second-branch]
#Show changes on a particular commit
git show [commit]
#Reset head to a particular commit, preserving changes locally
git reset [commit]
#Resets head and discards all history
git reset --hard [commit]
#Reset last two commits
git reset --hard HEAD^^
#Undo last commit and put the changes back to staging
git reset --soft HEAD^
#Amending last commit
git commit -amend -m "New message"
#Downloads all history of a particular branch
git fetch [branch-name]
#Download history and incorporate to local branch
git pull
git pull --rebase #does fetch + rebase. It is better.
git push
#Resetting head to an old point
git reset --hard 6ae0aa9c5cb678
#Clearing untracked files after hard reset
git clean -f -d
#Ignoring changes to two files
git checkout -- file1.txt file2.html
#Merging feature branch to develop branch
$ git checkout develop
#Switched to branch 'develop'
$ git merge --no-ff myfeature
#Updating ea1b82a..05e9557
#(Summary of changes)
$ git branch -d myfeature
#Deleted branch myfeature (was 05e9557).
$ git push origin develop
#Creating release branch from develop
$ git checkout -b release-1.2 develop
#Switched to a new branch "release-1.2"
$ ./bump-version.sh 1.2
#Files modified successfully, version bumped to 1.2.
$ git commit -a -m "Bumped version number to 1.2"
#[release-1.2 74d9424] Bumped version number to 1.2
#1 files changed, 1 insertions(+), 1 deletions(-)
#Merging changes to master and tagging
$ git checkout master
#Switched to branch 'master'
$ git merge --no-ff release-1.2
#Merge made by recursive.
#(Summary of changes)
$ git tag -a 1.2
#Merging same changes to develop
$ git checkout develop
#Switched to branch 'develop'
$ git merge --no-ff release-1.2
#Merge made by recursive.
#(Summary of changes)
#Deleting release branch
$ git branch -d release-1.2
#Creating hotfix branch and merging to master and develop branches
$ git checkout -b hotfix-1.2.1 master
#$ ./bump-version.sh 1.2.1
$ git commit -a -m "Bumped version number to 1.2.1 and applied fixes"
$ git checkout master
$ git merge --no-ff hotfix-1.2.1
$ git tag -a 1.2.1
$ git checkout develop
$ git merge --no-ff hotfix-1.2.1
#List Tags
git tag
#Checkout particular tag code
git checkout v0.1
#Creating new tag
git tag -a v0.2 -m "v0.2"
#Pushing tags to remote
git push --tags
#Rebase applies local commits after remote commits. This avoids a merge commit
#Rebasing master with remote master
git fetch
git rebase origin/master
#If conflict is there fix it, git add, then
git rebase --continue
#Manipulating last 3 commits using rebase
git rebase -i HEAD~3
#Then below options
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
# d, drop = remove commit
#Clone entire repo & rewriting history
git clone repoName filterRepo
git filter-branch --tree-filter anyShellCOmmand #[takes each commit, runs command, recommits]
git filter-branch --tree-filter anyShellCOmmand -- --all # to run in all commits and all branches
git filter-branch --tree-filter 'rm -f passwords.txt'
git filter-branch --tree-filter 'find . -name "*.mp4" -exec rm {} \;'
#or run below command to operate in staging are with git command
git filter-branch --index-filter 'git rm --cached --ignore-unmatch passwords.txt' --prune-empty -- --all
#To remove empty commits
git filter-branch -f --prune-empty -- --all
#Line endings
Unix /n
git config --global core.autocrlf input
Windows /n/r
git config --global core.autocrlf true
#Sample .gitAttributes
* text=auto
*.rb text
*.js text
*.bat text eol=crlf
*.sh text eol=lf
*.png binary
git cherry-pick commitId
git cherry-pick --edit commitId # to edit commit message
git cherry-pick --no-commit commit1 commit2 # pick multiple and stage
git cherry-pick -x commitId # keep same SHA
git cherry-pick --signoff commitId # adds name of cherry-picker
#Submodules
git submodule add remoteRepoName
#Any new local commits to submodule should be pushed to submodule remote and main repo remote seprately
#Any new user need to run below after clone
git submodule init
git submodule update # should be be used to refresh the repo anytime
#submodule update brings repo to headless state. To fix run below,
git checkout master
git merge hashShownInHeadlessState
#To abort push if submodule is not pushed
git push --recurse-submodules=check
#To automatically push submodules
git push --recurse-submodules=on-demand
#Alias it as below
git config --global alias.pushall "push --recurse-submodules=on-demand"
#Git stores backup in reflogs (Only available locally)
git reflog #-> to see backup. even after hard reset
or
git log --walk-reflogs #-> gives more details
view raw Git Commands.sh hosted with ❤ by GitHub

Explanation

You need to have a very high level idea about git to use this reference article. Just search in the page to find commands for common operations like cloning repo, creating branch, committing code, reverting code, stashing code etc.


How to use

Install Git CLI corresponding to your operating system from git website. Start running commands from above command reference.

Please note that if you do not want to use command line git, you can always depend on git clients like Github Desktop, SourceTree, TortoseGit, GitKraken and more others


How to use custom iterator in apex batch class

Apex batch classes are used to process large volume of records that can hit governor limits if processed synchronously. Batch classes are used to split these large set of records into small chunks and execute as separate transactions. Batch class can work on up to 50M sObject records using QueryLocator or upto 50k records using Iterator. Using list of sObjects is a common pattern and you can find a sample batch class template here. There are two ways of using iterator approach. it can either be a or a There are cases where using a Iterator is more meaningful. You can find some use cases below,

  1. Use a custom iterator defined using CustomIterable interface
  2. You can just use standard apex collections like list as iterator. Because they are implementing Iterable interface behind the scenes

Use cases

  • If your batch class needs to operate on data obtained from two unrelated objects, you can create a custom iterable class and return combined data from both objects as a list of iterable from start method
  • Say you have an API that returns ~5k product Ids and then you need to hit another API for each of these products to get more details about each product. You can return a list of product Ids from start method to achieve this.

/*******************************************************************************************
* @Name IteratorExampleBatch
* @Author FirstName LastName <author@email.com>
* @Date 01/13/2020
* @Group Apex Batches
* @Description This batch class demonstrates use of iterator in apex batch class.
*******************************************************************************************/
/* MODIFICATION LOG
* Version Developer Date Description
*-------------------------------------------------------------------------------------------
* 1.0 Firstname 01/13/2020 Initial Creation
*******************************************************************************************/
global class IteratorExampleBatch implements Database.Batchable<String>, Database.AllowsCallouts {
//Make sure you add below endpoint to remote site settings
private final String API_BASE = 'https://th-apex-http-callout.herokuapp.com/';
/**************************************************************************************
* @Description This method gets all animals, get corresponding animal IDs and sends to
* execute for processing
* @Param bc - BatchableContext
* @Return Iterable<String> - List of animals whose details need to be retrieved
**************************************************************************************/
global Iterable<String> start(Database.BatchableContext bc) {
List<String> animalIdList = new List<String>();
//Move the API call code to a separate class for reusability
Http http = new Http();
HttpRequest request = new HttpRequest();
request.setEndpoint(API_BASE+'animals');
request.setMethod('GET');
HttpResponse response = http.send(request);
if (response.getStatusCode() == 200) {
Map<String, Object> resultMap = (Map<String, Object>) JSON.deserializeUntyped(response.getBody());
for (Object animal: (List<Object>) resultMap.get('animals')) {
animalIdList.add((String)animal);
}
}
return animalIdList;
}
/**************************************************************************************
* @Description This method gets details of individual animal by hitting API
* @Param bc - BatchableContext
* @Param accountanimalIdListList - Chunk of animal Ids that needs to be processed
* @Return NA
**************************************************************************************/
global void execute(Database.BatchableContext bc, List<String> animalIdList){
//Do some heavy processing here. In this case get more details about each animal :)
//Move the API call code to a separate class for reusability
Http http = new Http();
HttpRequest request = new HttpRequest();
request.setMethod('GET');
for(String animalId: animalIdList) {
System.debug('Getting details about'+animalId);
request.setEndpoint(API_BASE+'animals/'+animalId);
HttpResponse response = http.send(request);
if (response.getStatusCode() == 200) {
Map<String, Object> resultMap = (Map<String, Object>) JSON.deserializeUntyped(response.getBody());
System.debug('Got details about animal ' + response.getBody());
//Bulkify the results and store in records
}else {
system.debug('Unable to get about animal => '+response.getStatusCode()+response.getBody());
}
}
}
/**************************************************************************************
* @Description This method executes any post-processing operations
* @Param bc - BatchableContext
* @Return NA
**************************************************************************************/
global void finish(Database.BatchableContext bc){
// execute any post-processing operations
}
}

Explanation

Apex batch classes can return an iterator to process large volume of data that are not directly queried from database/sobjects. These iterators can be classes implementing Iterable interface or standard apex data strucutres like list. In above example we are getting a list of animals and details of individual animal from an API hosted in Heroku. It is used by Salesforce for trailhead modules. Here "baseUrl/animals" gives a list of animals and "baseUrl/animals/animalId" gives details of a single animal.

Suppose the API to get list of animals gives back 1000 animal IDs. Then we cannot get details of all animals individually using single transaction. This is because currently governor limit on number of callouts in one transaction is 100. So we need to split it into multiple transactions. Best way to do this is to use apex batch. Here we use start method to make an API call to get list of all animals. Then we will process the result and finally start method will return a list of all animal Ids to execute method. Then because it is a batch, Salesforce will call execute method multiple times with a subset of total animal list each time using the batch size we specify while starting the batch. This will help us to stay within governor limits if we use correct batch size (Something below 100 in our case so that we can stay within 100 callouts per transaction limit).


How to use

  • Make sure that you are adding https://th-apex-http-callout.herokuapp.com/ in remote site settings to allow callouts to this URL.
  • Create an apex class with name "IteratorExampleBatch" and copy paste the code from above
  • Execute the batch using "Developer Console" => "Execute Anonymous" option. You can use Database.executeBatch(new IteratorExampleBatch(), 10); to execute batch with a batch size of 10

How to use lightning data service in lightning web components(LWC)

Lightning data service allows you to cache and share data between lightning components using browser cache. Lightning framework takes care of managing cached data in browser. You do not need to write any code to interact with browser cache. There is no need to write any apex code also. Since the data is coming from client/browser cache, you can access data quickly if it is cached already. Lightning data service is built on top of Salesforce user interface API.

Use cases

  • Create simple forms that can create/view/edit single record.
  • lightning-record-form can be used to display data from all fields in standard page layout.
  • If you are building a component to use in a record details page and the component only updates the fields in the same record, it is highly recommended to use lightning data service, since Salesforce keeps data in sync with details page automatically.

<template>
<lightning-card title="Lightning Data Service">
<p class="slds-p-horizontal_small">
<lightning-input type="checkbox" label="Checkbox Field" name="input1" onchange={handleFieldChange} checked={checkboxValue}></lightning-input>
</p>
</lightning-card>
</template>
import { LightningElement, wire, api } from 'lwc';
import { getRecord, getFieldValue, updateRecord } from 'lightning/uiRecordApi';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
import ID_FIELD from '@salesforce/schema/Contact.Id';
import MY_CHECKBOX_FIELD from '@salesforce/schema/Contact.My_Checkbox_Field__c';
export default class LwcDataserviceComponentt extends LightningElement {
@api recordId;
@wire(getRecord, { recordId: '$recordId',
fields: [ID_FIELD, MY_CHECKBOX_FIELD],
optionalFields: []
})
contact;
get checkboxValue() {
return getFieldValue(this.contact.data, MY_CHECKBOX_FIELD);
}
handleFieldChange(event) {
const fields = {};
fields[ID_FIELD.fieldApiName] = this.recordId;
fields[MY_CHECKBOX_FIELD.fieldApiName] = event.target.checked;
const contactToUpdate = { fields };
this.updateContact(contactToUpdate);
}
updateContact(contactToUpdate) {
updateRecord(contactToUpdate)
.then(() => {
this.dispatchEvent(
new ShowToastEvent({
title: 'Success',
message: 'checkbox Updated',
variant: 'success'
})
);
})
.catch(error => {
this.dispatchEvent(
new ShowToastEvent({
title: 'Error occurred while updating checkbox',
message: error.body.message,
variant: 'error'
})
);
});
}
}
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>47.0</apiVersion>
<isExposed>true</isExposed>
<description>This component demonstrates using lightning data service in lwc components.</description>
<targets>
<target>lightning__RecordPage</target>
</targets>
<targetConfigs>
<targetConfig targets="lightning__RecordPage">
<objects>
<object>Contact</object>
</objects>
</targetConfig>
</targetConfigs>
</LightningComponentBundle>

Explanation

You can use "getRecord" and "updateRecord" methods from "lightning/uiRecordApi" to get record and update record from lightning data service respectively. After getting a record you need to wire it to a variable to make it available in UI. Then you need to use "getFieldValue" method and create a getter method to make the field available in the UI.

If we go step by step in the flow, below actions happen in a sequence when the component is loaded and value is changed.

  1. Component gets loaded in a record details page and salesforce passes "recordId" attribute is passed in to the component
  2. @wire annotation uses "getRecord" to get data from Salesforce server using lightning data service
  3. This data is made available to HTML through "checkboxValue" getter method. At this point if the data in contact record is checked, it will be dispalyed in UI
  4. Say user changed the value of checkbox by clicking it. "handleFieldChange" method is called. This method creates an object to update and passes to "updateContact" method
  5. "updateContact" method uses "updateRecord" method from lightning data service to send this data to Salesforce server and update
  6. Based on success or failure, a toast message is shown by firing an eveng


How to use

  • This code assumes that you have a checkbox field in your contact object with API name "My_Checkbox_Field__c"
  • Create an LWC component with name "lwcDataserviceComponent". Copy HTML, JS and XML code above to relevant files
  • Once the component is saved, you should be able to see it in app builder interface for contact object. This is because we have made it available through the metadata file of lightning component
  • Drag and drop the component to contact page and activate it
  • If you have the same field in record details section, you will be able to see that getting updated in real time as you update the checkbox in the lwc component.

How to pass attributes from aura component to lightning web component(lwc)

We can compose aura components and aura apps with a combination of lwc components and aura components. Frequently we need to pass attributes from aura component to lightning web component. Here we go through the an example of passing data from aura to lwc component


<template>
Value received from parent aura component to child lwc component ==> <b>{childVariable}</b>
</template>
import { LightningElement, api } from 'lwc';
export default class ChildLWCComponent extends LightningElement {
@api childVariable;
}
<aura:component >
<c:childLWCComponent childVariable="Value sent from parent"></c:childLWCComponent>
</aura:component>

Explanation

Here we are creating an LWC component with name "childLWCComponent". We display data received from parent aura component "ParentAuraComponent" in "childLWCComponent". In order to make an lwc Javascript variable/attribute available for parent components to pass data, we need to add @api annotation before the variable. In order to pass data to "childLWCComponent" LWC component from parent aura component, you can just use the syntax <c:childLWCComponent childVariable="Value sent from parent"></c:childLWCComponent>


How to use

  • Create an LWC component with name childLWCComponent
  • Copy content from above code to childLWCComponent component. childLWCComponent.html is the HTML file and childLWCComponent.js is the Javascript file
  • Create an aura component with name "ParentAuraComponent"
  • Copy content from above code sample to ParentAuraComponent.cmp file
  • You can embed the parent aura component in an aura app to see the result

How to use a lightning web components(LWC) inside an aura component

It is very easy to embed lightning web components(lwc) inside aura components. But remember that you cannot insert an aura component inside an LWC component.

Use cases

  • You can use this approach to migrate/modernize your big aura applications to LWC step by step. Suppose there is a big aura application that has four big aura sub components. We can migrate the application to LWC framework, by migrating one of these four aura components to LWC at a time.

<template>
This text is in LWC component which contains a dynamic variable with value <b>{testVariable}</b>
</template>
import { LightningElement, track } from 'lwc';
export default class ChildLWCComponent extends LightningElement {
@track testVariable = 'Hi from JavaScript';
}
<aura:application extends="force:slds">
<!-- To see the result easily, we are using an aura application instead of aura component.
But the syntax is the same-->
<c:childLWCComponent></c:childLWCComponent>
</aura:application>
view raw TestApp.app hosted with ❤ by GitHub

Explanation

Here we are creating an LWC component with name "childLWCComponent". We display data from a javascript variable in controller with name "testVariable" in the UI. To embed we are using an aura application with name TestApp. In order to embed "childLWCComponent" LWC component in aura app, you can just use the syntax "<c:childLWCComponent></c:childLWCComponent>"


How to use

  • Create an LWC component with name childLWCComponent
  • Copy content from above code to childLWCComponent component. childLWCComponent.html is the HTML file and childLWCComponent.js is the Javascript file
  • Create an aura app with name "Testapp.app"
  • Copy content from above code sample to Testapp.app file
  • Navigate to "yourOrgBaseUrl/c/TestApp.app" to see the result

How to display a modal window using lightning web components

We will go through building a reusable lightning web component that you can use to show modal windows in other LWC components.

Use cases

  • Display modal window or popup window in user interface

<template>
<h1>Parent component</h1>
<lightning-button variant="brand" label="Open Modal" title="Open Modal" onclick={showModalPopup} class="slds-m-left_x-small"></lightning-button>
<c-util-modal
show-modal={showModal}
show-positive={showPositiveButton}
positive-button-label={positiveButtonLabel}
show-negative={showNegativeButton}
onpositive={closeModal}
onclose={closeModal}>
<div slot="header">
<h2 slot="header" id="modal-heading-01" class="slds-text-heading_medium slds-hyphenate">Header from parent component</h2>
</div>
<div slot="body">
Static or dynamic body content from parent. Can include other child lwc components also.
</div>
</c-util-modal>
</template>
import { LightningElement, track } from 'lwc';
export default class ModalParentExample extends LightningElement {
//Variables to control modal window
@track showModal = false;
@track showNegativeButton;
@track showPositiveButton = true;
@track positiveButtonLabel = 'Close';
closeModal() {
this.showModal = false;
}
showModalPopup() {
this.showModal = true;
}
}
<template>
<template if:true={showModal}>
<div>
<section role="dialog" tabindex="-1" aria-labelledby="modal-heading-01" aria-modal="true"
aria-describedby="modal-content-id-1" class="slds-modal slds-fade-in-open">
<div class="slds-modal__container" style="align-items: center;">
<header class="slds-modal__header" style="min-width: 1100px;">
<button class="slds-button slds-button_icon slds-modal__close slds-button_icon-inverse"
title="Close" onclick={handleClose}>
<lightning-icon icon-name="utility:close" alternative-text="close" variant="warning"></lightning-icon>
<span class="slds-assistive-text">Close</span>
</button>
<slot name="header">
<h2 id="modal-heading-01" class="slds-text-heading_medium slds-hyphenate">Header</h2>
</slot>
</header>
<div class="slds-modal__content slds-p-around_medium" id="modal-content-id-1" style="min-width: 1100px;">
<slot name="body">
<p>Body goes here..</p>
</slot>
</div>
<footer class="slds-modal__footer" style="min-width: 1100px;">
<template if:true={showNegative}>
<button class="slds-button slds-button_neutral" onclick={handleNegative}>{negativeButtonLabel}</button>
</template>
<template if:true={showPositive}>
<button class="slds-button slds-button_brand" onclick={handlePositive}>{positiveButtonLabel}</button>
</template>
</footer>
</div>
</section>
<div class="slds-backdrop slds-backdrop_open"></div>
</div>
</template>
</template>
view raw utilModal.html hosted with ❤ by GitHub
import { LightningElement, api } from 'lwc';
export default class UtilModal extends LightningElement {
@api showPositive;
@api showNegative;
@api positiveButtonLabel = 'Save';
@api negativeButtonLabel = 'Cancel';
@api showModal;
constructor() {
super();
this.showNegative = true;
this.showPositive = true;
this.showModal = false;
}
handlePositive() {
this.dispatchEvent(new CustomEvent('positive'));
}
handleNegative() {
this.dispatchEvent(new CustomEvent('negative'));
}
handleClose() {
this.dispatchEvent(new CustomEvent('close'));
}
}
view raw utilModal.js hosted with ❤ by GitHub

Explanation

We can use lightning design system sample modal code in the link to show the modal window. But to implement opening and closing behavior of the modal, we need to use javascript variables in lwc. We will create a reusable lwc component with name "utilModal". This will have code needed to show and hide modal window. Then we will create a sample parent component with name "modalParentExample" that we can use embed modal component. We fire custom events from utilModal component and parent "modalParentExample" catches these events. Parent component can use these action handlers to execute actions when buttons in modal window are clicked.

How to use

  • Create an LWC component with name utilModal
  • Copy content from above code to utilModal component. utilModal.html is the HTML file and utilModal.js is the Javascript file
  • "modalParentExample" has sample code to open modal window