function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Marty BremerMarty Bremer 

How to dynamically change the background image of a class within a lightning component?

I am using the lightning:fileUpload component and have been successful in changing it's appearance to look similar to the following: 

User-added image

When the user clicks on the image they are able to take a picture and upload it successfully.  I was able to accomplish the look of this fileUpload component by changing the .css as:

.THIS .slds-file-selector__body {
    background-image: url(/resource/open_bite_right);
    height: 84px;
    width: 84px; 
}

My problem is that I have a dozen other fileUpload components that each have a different background image.  Without creating a dozen aura:components is there another way to dynamically change the background image?

The issue I am having is that the slds-file-selector__body class is buried within the inputFile component.  Changing the class on the inputFile component itself is no good because that only changes the class of the parent component.

My desire is to have a single aura:component that includes this lightning:fileInput component, and then set attributes on the component to change its look and functionality.  My only limitation at this point is being able to somehow get to the slds-file-selector__body within the fileInput component and dynamically change its background.
Dev_AryaDev_Arya
Hi Marty,

Its a wild guess but lets see. If you are using the aura:component at different places that means there would be some way of getting some context variable, or any attribute which distinguishes the aura:component context,  based on that context variable or attribute, using <aura:if> or javascript, you can decide an additional class for the lightning:fileInput component and define background image for that class. I can try this in my dev org tomorrow and will provide further inputs. But I think this is achievable. 

Cheers,
Dev
Marty BremerMarty Bremer
Hi Dev,

You are correct, there is additional context for each aura:component.  When the component is insantiated, I am also setting an aura:attribute that contains the context. Based on that attribute I am able to determine which background I want to use, I just can’t figure out anyway of setting that background programmatically since the needed class is buried within the lightning:fileInput component.
Dev_AryaDev_Arya
Hi Marty,

I think I got this, instead of changing the lightning:fileInput component class 'slds-file-selector__body', based on the attribute value I added a dynamic class to the component (using jquery) in my render funtion, and in the .css definition of the component, declared classes with the bg image. You can also add the image while adding the class. Below is the code, 
// declaration of the input file. Notice the aura:id in label tag, need this for finding the component
<aura:attribute name="testbg" type="boolean" default="true"/>
<label class="slds-file-selector__body" aura:id="testcomm" for="file-upload-input-01">

// here is the css

.THIS .custom-bg{
    background-image: url(/resource/testImage);
}
.THIS .custom-bg_new{
    background-image: url(/resource/little_insight);
}

// and here goes the jquery
render : function(cmp, helper) {
        var ret = this.superRender();

        var comp = cmp.find('testcomm');
        var label = cmp.get("v.testbg");
        if(label){
            $A.util.addClass(comp, "custom-bg");
            //$('div.custom-bg').css('background-image','url(/resource/testImage)');
        }
        else{
            $A.util.addClass(comp, "custom-bg_new");
            //$('div.custom-bg').css('background-image','url(/resource/little_insight)');
        }
        // do custom rendering here
        //alert('this is Render');
        return ret;
}

In the render function, i fetched the value of the attribute, based on that value added a class to the component. You can also add the image while adding the class (commented lines in the js). To me, this is not the most elegant solution, but it works.

Hope this helps.

Cheers & happy coding,
Dev
 
Marty BremerMarty Bremer
Hi Dev,

I still can't seem to make this work for some reason.  I have simplified down the sample code here:

aura:component
<aura:component implements="force:appHostable">
 
    <lightning:input type="file" 
                                                 files="{!v.fileToBeUploaded}"
                                                 label=""
                                                 disabled="FALSE"
                                                 name="Front" 
                                                 multiple="true" 
                                                 accept="image/png, image/jpg" />
    
</aura:component>

css
/*get rid of the right label*/
.THIS .slds-file-selector__dropzone .slds-file-selector__text{ 
    display: none;
}

/*To override the text, you'll need to set the size of the current text to 0*/
.THIS .slds-file-selector__dropzone .slds-file-selector__button {
    display: none;
}

/*set the size of the button and background image*/
.THIS .slds-file-selector__body {
	background-image: url(/resource/smilestore_open_bite_right);
    height: 84px;
    width: 84px; 
}

/*get rid of the label*/
.THIS .slds-form-element__label{
     display: none;
}

Notice how I'm using the lightning:input type="file", but have to get at the slds-file-selector__body class to change the background image.  How can I change it to dynamically replace the background within that specific lightning:input component?
Marty BremerMarty Bremer
Dev,

After doing a bit more research, it seems like it would work best if I could add the image while loading the slds-file-selector__body class.  Something like:

$('div.slds-file-selector__body').css('background-image','url(/resource/smilestore_open_bite_right)');

in renderer.js.  But what is the correct syntax to get at the slds-file-selector__body within the lightning:input component?  I keep getting the following error stating that '$' doesn't exist:

User-added image

 
Dev_AryaDev_Arya
Hi Marty,

it was my mistake, the jquery wont work in the render function as it is loaded after the render function is processed.
I moved my code to the afterScriptsLoaded="{!c.check}", and it works there.  Below is the entire code. 
// aura component : i took the file load code from this blog (a random search): http://hellosnl.blogspot.de/2017/08/lightning-component-for-attaching-files_1.html
<aura:component description="DevComm_9060G000000MUdMQAW" implements="force:appHostable">
    <ltng:require scripts="{!$Resource.jquerymin}" afterScriptsLoaded="{!c.check}"/>
    <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>

    <aura:attribute name="testbg" type="boolean" default="true"/>
    <h1 id="message"></h1>
    <div class="slds-form-element">
        <span class="slds-form-element__label" id="file-selector-id">Attachment</span>
        <div class="slds-form-element__control">
            <div class="slds-file-selector slds-file-selector_files">
                <div class="slds-file-selector__dropzone">
                    <input type="file" class="slds-file-selector__input slds-assistive-text" accept="image/png" id="file-upload-input-01" aria-describedby="file-selector-id" aura:id="file" onchange="{!c.showfile}"/>
                    <label class="slds-file-selector__body" aura:id="testcomm" for="file-upload-input-01">
                    <span class="slds-file-selector__button slds-button slds-button_neutral">
                        Upload Files
                    </span>
                        <span class="slds-file-selector__text slds-medium-show">or Drop Files</span>
                    </label>
                </div>
            </div>
        </div>
    </div>
</aura:component>

// javascript controller
/**
 * Created by darya on 11/11/2017.
 */
({
    doInit : function(component, event, helper) {
        //alert('this is init');

    },
    check:function (component, event, helper){
      //alert("Hello! jquerry initiate");
      var comp = component.find('testcomm');
        var label = component.get("v.testbg");
        if(label){
            $A.util.addClass(comp, "custom-bg");
            //$('.custom-bg').css('background-image','url(/resource/testImage)');
        }
        else{
            $A.util.addClass(comp, "custom-bg_new");
            //$('.custom-bg').css('background-image','url(/resource/little_insight)');
        }
    },
    showfile:function(component,event,helper){
        //TODO
    }
})

//CSS file
.THIS {
}

.THIS .slds-file-selector__body {

    height: 100px;
    width: 284px;
}

.THIS .custom-bg{
    background-image: url(/resource/testImage);
}
.THIS .custom-bg_new{
    background-image: url(/resource/little_insight);
}

.THIS div span
{
  color: red;
}


I will test with lightning:input component latter today.

Cheers,
Dev
Dev_AryaDev_Arya
Hi Marty,
if that solves your problem, could you please mark the question as green.
Cheers,Dev
Marty BremerMarty Bremer
Hi Dev,

Unfortunately it doesn't solve the problem.  If you test this using the lightning:input component, you will see the issue.