Setup web-to-lead form with dependent country and state fields in Salesforce

This is a question which I came across on the success community and which made me realise that it could be something which admins always look for an answer. Through this blog post I am going to give a simple solution which can even used by a Salesforce Admin who is not good with code. If you are a Salesforce Admin then you simple need to follow these steps.

  • Go to Web-to-Lead Setup and click Create Web-to-Lead Form button
  • Select the fields which you want see on the web form including State/Province and Country
  • Click the Generate button and add the following javascript code at the end of your generated code

 

Sample Complete html file with Javascript code

 

 

JSFiddle to the Web-to-lead form with state and country dependent pick list fields.

https://jsfiddle.net/h3v4msju/

I hope it helps!!

Clone Opportunity with Products action on Opportunities ( Lightning Component )

I am following this idea since I needed this feature in one of my projects. Since Salesforce already has this in their future roadmap, I realized that It could be an addition to my #GivingBackToCommunity list. I managed to create a lightning component which can be used with lightning action on Opportunity records. This will allow users to clone an opportunity with the products.

IdeaExchange Idea

Here is the idea on the IdeaExchange

clone with products

Lightning Component for Clone with Products

Here is the link to the Lightning Component GitHub repository
clone with products

 

Steps to Install/Configure this component in your Org

For Sandbox/Dev Environment

First, you need to identify whether you want to install a managed or unmanaged package. This can be determined based on your purpose. If you want to amend existing functionality then the unmanaged package is what you are looking for. If that’s not the case and you just want to test it before installing it to the production then managed package is your best bet.

  1. Install the package in your Org. Following are the links to the package installation URL.
    Link to unmanaged package
    Link to managed package
  2. After installing package successfully, you need to configure it and you will have to switch to Salesforce classic view as you need to update the fieldsets ( fieldsets are not available in lightning experience till Winter ‘2018 release).
  3. You have 2 fieldsets first one on Opportunity object and the second one on the OpportunityProduct object. These fieldsets let you decide which field values you want to copy to new opportunity ( cloned opportunity ). By default, it will copy those fields only which are required to save the record.
  4. To modify the fieldset fields navigate to Setup | Customize | Opportunity | FieldSets and you will find the Clone Opportunity Field Set.
  5. You can add fields which you want to be copied in the new opportunity. See the below screenshot.
  6. After adding the fields in the fieldset, you need to add action to the page layout. So navigate to the page layout section and drag the “Clone with Products” action on the pane.
  7. Save everything and switch back to lightning experience view to use this feature.
Screenshot_9
Clone Opportunity Field Set

 

Screenshot_10
Lightning action in page layout

 

For Production Environment

  1. Install the package in your Org. Following are the links to the package installation URL.
    Link to managed package

Rest steps are same as explained for the sandbox environment.

Please let me know if you have any feedback on this.

 

Salesforce Cookies #13

How to validate fields in lightning components ( Form Validation in Lightning Component )

Some lightning components come with inbuilt validation and you need to trigger the validation in your client-side controller. Following components provide inbuilt validation support.

  • lightning:input
  • lightning:select
  • lightning:textarea
  • ui:input*

lightning:input is more powerful when it comes to the validation as it honors the HTML5 validations too like setting the min and max limit on an element.

For the components which are part of the “ui” namespace like ui:input, you need to check it manually in the client-side code. These components have a property which is “errors” and you can set a list of errors to that property which will be displayed alongside the ui:input component.

How to add an error to ui:input

Adding an error to a ui:input is very simple. You just need to check whether it’s having the clean data or not and then add the error to the component.

var emailCmp = component.find("email");
var email = inputCmp.get("v.value");
var filter = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/;
// If it's blank
if ( email ) {
 // Set error
 emailCmp.set("v.errors", [{message:"Email is required"}]);
}
else if ( !filter.test( email ) ) {
    emailCmp.set("v.errors", [{message:"Email is not valid"}]);

 

I hope it explains a basic approach towards the validation. Please feel free to comment as it really important for the improvements.

 

 

How to create charts using D3 Library in Lightning Components

D3.js is the most popular library for creating interactive charts in any web application. You can also use D3.js library in Lightning components for graphical representation of data. These charts can be used to give sales insights to a member ( Salesforce user) of the sales team.  This article will show how can we leverage D3.js to build charts with a simple example.

First, let’s see the component code.

D3Charts.cmp

Screenshot_2

D3ChartsController.js
({
    initD3Charts : function(component, event, helper) {

        var width = 960;
        var height = 500;

        // Create SVG element, we can't just use  tag in lightning component
        // So creating one dynamically using jquery
        var svg = d3.select("body")
        .append("svg")
        .attr("width", width)
        .attr("height", height);	

        // Calling server-action to get the data
        var action = component.get("c.getData");

        // Create a callback that is executed after
        // the server-side action returns
        action.setCallback(this, function(response) {
            var state = response.getState();
            if (state === "SUCCESS") {
                let data = response.getReturnValue();
                console.log(data);
                // Render the returned data as a pie chart
                helper.renderChart( component, data );
            }
            else if(state === "ERROR") {
                var errors = response.getError();
                if (errors) {
                    if (errors[0] && errors[0].message) {
                        console.log("Error message: " +
                                    errors[0].message);
                    }
                } else {
                    console.log("Unknown error");
                }
            }
        });

        $A.enqueueAction(action);

    }
})
D3ChartsHelper.js
({
    renderChart : function( component, data ) {
        var svg = d3.select("svg"),
            width = +svg.attr("width"),
            height = +svg.attr("height"),
            radius = Math.min(width, height) / 2,
            g = svg.append("g").attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");

        var color = d3.scaleOrdinal(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]);

        var pie = d3.pie()
        .sort(null)
        .value(function(d) { return d.candidates; });

        var path = d3.arc()
        .outerRadius(radius - 10)
        .innerRadius(0);

        var label = d3.arc()
        .outerRadius(radius - 80)
        .innerRadius(radius - 80);

        var arc = g.selectAll(".arc")
        .data(pie(data))
        .enter().append("g")
        .attr("class", "arc");

        arc.append("path")
        .attr("d", path)
        .attr("fill", function(d) { return color(d.data.age); });

        arc.append("text")
        .attr("transform", function(d) { return "translate(" + label.centroid(d) + ")"; })
        .attr("dy", "0.35em")
        .text(function(d) { return d.data.age; });
    }
})

So, we have included d3.js library along with jquery.js and then called a server-side action when the script has loaded in order to fetch the chart data. In the defined callback function we passed that data to a helper function which rendered the chart.

D3ChartsController.apex
public class D3ChartsController {
  
    @AuraEnabled
    public static List getData(){
      
        // For this example, it's just a static data but it can be generated 
        // as per any business logic
        List lstData = new List();
        lstData.add( new PieChart( '=65', 61 ) );
        return lstData;
    }
    
    public class PieChart {
        @AuraEnabled public String age;
        @AuraEnabled public Integer candidates;
        
        public PieChart( String age, Integer candidates ) {
            this.age = age;
            this.candidates = candidates;
        }
    }
}
Screenshot_4
Preview

Reference to resources –

 

How to create table with resizable columns using Lightning Design System ( Column Resizable DataTable )

Lightning design system comes with some really nice cascading stylesheet but still, there are some components where JS support is not provided. During a project, I came across the same where I had to write Javascript code by myself. After going many rounds of testing and changes, finally, I managed to get it working. It’s Data Table component which I am talking about.

How does the column resizing work?

I have used mousedown and mousemove events to recognize the mouse cursor moment. Resizable columns have a divider which let users change the column width. You can check the following Gist for the code.

LINK TO SAMPLE CODE

Table

Please feel free to comment your question/suggestions in the comment box.

Salesforce Cookies #12

How to remove the arrows from lightning:input[type=”number”]?

I think this is a generic question and Salesforce devs have looked for the ways to get rid of the spin buttons on the input field without changing it to text type for a purely numeric behaviour. You just need a few lines of CSS to solve your problem.

We need some CSS which work across the browsers. Any browser like Safari, Chrome and Firefox have a specific bahaviour for number type inputs.

Component.css

In the CSS component of the Lightning component bundle, we need to include the following styling.

/* For Firefox browser */
.THIS input[type='number'] {  
   -moz-appearance:textfield;
}
/* For webkit browsers like Chrome and Safari */
.THIS input[type=number]::-webkit-inner-spin-button,
.THIS input[type=number]::-webkit-outer-spin-button {
   -webkit-appearance: none;
   margin: 0;
}

So it will look like as shown here.

Screenshot_2     Screenshot_1

In case if you have any concern or queries then please feel free to comment on the post.

Have fun with the CSS!!