Hi Everyone
I am here with some cool stuff. As you know that YouTube is very popular for videos. Many of salesforce videos on YouTube as well. After reading this post, you can search videos in salesforce1 and also you can share to chatter as well.
We will learn following things in this post :
1. Lightning Components
2. Lightning Design System with lightning Components
3. YouTube Integration
4. Wrapper Classes in lightning
5. Nested Components
6. Passing values from child to parent Component
7. Creating app on google console
First of all we need a google API key to fetch data for YouTube. For getting API key we need to create a App on google console.
A. Get a API key from Google :
1. Go to https://console.developers.google.com
2. Create a new project here.
3. A pop-up will open, fill all project’s info here, Then click on Create button.
4. Now navigate to left panel and select APIs & Auth –> APIs
5. Then click on YouTube Data API under YouTube APIs section.
6. Then press Enable API button to enable YouTube’s API.
7. After that Go to Credentials then click on Add Credential –> Api Key
8. A popup will open, select Server Key option here.
9. Now give Server Api Key name here and click on create. now you have your Api Key. Please do secure your API key.
B. Building Lighting Components and Apex Classes:
1. YouTubeFeedCtrl.cls
2. YouTubeWrraper.cls
3. YouTubeJSON.cls
4. YouTubeToFeed.cmp
5. YouTubeToFeedContoller.js
6. YouTubeViewPort.cmp
7. YouTubeViewPortContoller.js
1.YouTubeFeedCtrl.cls
This class used for fetching data from google API and sharing feeds on chatter. We are making request on http://www.googleapis.com and filling wrapper class list from response of http request.
public with sharing class YouTubeFeedCtrl{ private static final String SEARCH_URL = 'https://www.googleapis.com/youtube/v3/search'; private static final String API_KEY = 'AIzaSyC60-a9ziN9zLIcb9ueYv2-IwS03CnYgI4'; //API_KEY //Fetching youtube data by given search string @AuraEnabled public static List fetchVideos(string searchString){ //If no search keywords found then it will search for salesforce keyword searchString = searchString == null ? 'salesforce' : searchString ; //Making Http request to google apis Http http = new Http(); HttpRequest req = new HttpRequest(); HttpResponse res = null; String endpoint = SEARCH_URL + '?part=snippet' + '&maxResults=20' + '&type=video' + '&q=' + EncodingUtil.urlEncode(searchString, 'UTF-8') + '&key=' + API_KEY; req.setEndPoint(endpoint); req.setMethod('GET'); res = http.send(req); //Deserializing json data YouTubeJSON.Response response = (YouTubeJSON.Response)JSON.deserialize(res.getBody(), YouTubeJSON.Response.class); List items = response.items; //Filling Wrapper Data for lightning component List LstYTWrapper = new List(); For( YouTubeJSON.Item itemObj : items ){ YouTubeWrapper YuTuWr = new YouTubeWrapper(); YuTuWr.videoId = itemObj.id.videoId; YuTuWr.title = itemObj.snippet.title; YuTuWr.Description = itemObj.snippet.description; YuTuWr.thumbnails = itemObj.snippet.thumbnails.medium.url; YuTuWr.channelTitle = itemObj.snippet.channelTitle ; YuTuWr.publishedAt = itemObj.snippet.publishedAt+''; LstYTWrapper.add(YuTuWr); } return LstYTWrapper; } //Function for share youtube link to chatter @AuraEnabled public static boolean shareOnChatter(string chatterText,String youTubeUrl){ chatterText = chatterText == null ? '' : chatterText ; FeedItem post = new FeedItem(); post.ParentId = userinfo.getUserId(); post.Body = chatterText; post.LinkUrl = youTubeUrl; insert post; return true; } }
2. YouTubeWrraper.cls
Lightning wrapper classes different from salesforce wrapper classes. We can’t access inner classes in lightning so we are not creating wrapper class as inner class here. In wrapper classes each variable should be @AuraEnabled.
public class YouTubeWrapper{ @AuraEnabled public String videoId { get; set; } @AuraEnabled public String Description { get; set; } @AuraEnabled public String thumbnails{ get; set; } @AuraEnabled public String title { get; set; } @AuraEnabled public String channelTitle { get; set; } @AuraEnabled public String publishedAt { get; set; } }
3. YouTubeJSON.cls
This class contains wrapper classes for json de-serialization.
public class YouTubeJSON{ public List items { get; set; } public class Response { public String kind { get; set; } public String etag { get; set; } public String nextPageToken { get; set; } public String prevPageToken { get; set; } public YouTubeJSON.PageInfo pageInfo { get; set; } public List items { get; set; } } public class PageInfo { public Integer totalResults { get; set; } public Integer resultsPerPage { get; set; } } public class Item { public String kind { get; set; } public String etag { get; set; } public YouTubeJSON.Id id { get; set; } public YouTubeJSON.Snippet snippet { get; set; } } public class Id { public String kind { get; set; } public String videoId { get; set; } } public class Snippet { public Datetime publishedAt { get; set; } public String channelId { get; set; } public String title { get; set; } public String description { get; set; } public YouTubeJSON.Thumbnails thumbnails { get; set; } public String channelTitle { get; set; } public String liveBroadcastContent { get; set; } } public class Thumbnails { public YouTubeJSON.Thumbnail medium { get; set; } public YouTubeJSON.Thumbnail high { get; set; } } public class Thumbnail { public String url { get; set; } } }
4. YouTubeFeed.cmp
From here we are going to develop lightning part for this app. This is our main component, we will use this component to show our app in salesforce1. In this component we are defining success message, iframe for YouTube videos, searching of videos on YouTube and share videos link on chatter.
<!--Describing Youtube video id for Parent Component(YouTubeFeed.cmp)--> <!--Describing attribut of YouTubeWrapper class--> <!--Including Lightninh Design System resource--> <!--Calling doSearch function on loading of component--> <div class="slds" style="background-color:#F4F6F9;"> <!--Success Message Start Here--> <div id="ChatterSuccessMessage" class="slds-notify-container" style="display:none;"> <div class="slds-notify slds-notify--toast slds-theme--success" role="alert" style="min-width:0;"> <span class="slds-assistive-text">Info</span> <div class="notify__content"> <h2 class="slds-text-heading--small">Feed succefully posted...</h2> </div> </div> </div> <!--Success Message End Here--> <!--Header Start Here--> <div class="slds-page-header" role="banner"> <div class="slds-grid"> <div class="slds-col slds-has-flexi-truncate"> <div class="slds-media"> <div class="slds-media__figure"> <b style="color:red;">Youtube</b><b style="font-size:45px;">2</b><b style="color:blue;">Chatter</b> </div> </div> </div> </div> <div class="slds-grid"> <div class="slds-col--padded slds-size--3-of-4"> <!--Input box for taking search string for videos--> </div> <div class="slds-col--padded slds-size--1-of-4"> <!--Search Button--> Search </div> </div> </div> <!--Header End Here--> <!--Container Start Here--> <div class="slds-container--fluid slds-container--center"> <div class="slds-grid" id="youtubeframe" style="display:none;"> <div class="slds-card slds-card--empty" style="width:100%;"> <div class="slds-card__body" style="padding:0;"> </div> <div class="slds-grid slds-m-top--medium slds-m-bottom--medium"> <div class="slds-col slds-size--1-of-2"> <!--Chatter Feed Message--> </div> <div class="slds-col slds-size--1-of-2"> <!--Share on chatter button--> Share to Chatter </div> </div> </div> </div> <div class="slds-grid slds-m-top--medium"> <div class="slds-col"> <ul class="slds-timeline" style="background-color:#F4F6F9;"> <!--Passing youtube records in YouTubeViewPort Component using Iteration--> </ul> </div> </div> </div> <!--Container Start Here--> </div>
5. YouTubeToFeedContoller.js
This is the controller of YouTubeToFeed.cmp. Here are two methods first one is used for fetch data and set data to wrapper attribute on YouTubeToFeed.cmp and second one is used to share feed on chatter.
({ //Searching and getting data from apex class doSearch: function(cmp, event, helper) { var fetchVideo = cmp.get("c.fetchVideos"); fetchVideo.setParams({ searchString: cmp.find("searchstr").get("v.value") }); fetchVideo.setCallback(this, function(response) { var state = response.getState(); if (state === "SUCCESS") { cmp.set("v.YouTubeVideos", response.getReturnValue()); } else if (state === "ERROR") { var errors = response.getError(); if (errors) { if (errors[0] &amp;&amp; errors[0].message) { $A.error("Error message: " + errors[0].message); } } else { $A.error("Unknown error"); } } }); $A.enqueueAction(fetchVideo); }, //Posting feeds to chatter shareOnChatterClient: function(cmp, event, helper) { var myVar; var shareOnChatterAuraFun = cmp.get("c.shareOnChatter"); //Passing params to apex shareOnChatter function shareOnChatterAuraFun.setParams({ "chatterText": cmp.find("chatterStr").get("v.value"), "youTubeUrl": cmp.get("v.ParentviewIt") }); shareOnChatterAuraFun.setCallback(this, function(response) { var state = response.getState(); //If result is successfull then notification will apears for 5 second if (state === "SUCCESS") { document.getElementById("ChatterSuccessMessage").style.display = 'block'; //Run a interval and call eraseSuccessMessage in 5 second to hide notification myVar = setInterval(function() { eraseSuccessMessage(); }, 5000); } }); $A.enqueueAction(shareOnChatterAuraFun); //Function for hide notification function eraseSuccessMessage() { document.getElementById("ChatterSuccessMessage").style.display = 'none'; clearInterval(myVar); } } })
6. YouTubeViewPort.cmp
In this component, I am implementing nested components concept in lightning. This is child component of YouTubeToFeed.cmp. Here we are filing data of for each
<!--Describing Youtube video id for Child Component(YouViePort.cmp)--> <!--Describing attribut of YouTubeWrapper Variable--> <li class="slds-timeline__item"> <span class="slds-assistive-text">Event</span> <div class="slds-media slds-media--reverse"> <div class="slds-media__body"> <div class="slds-media slds-media--timeline slds-timeline__media--event"> <div class="slds-media__figure"> <img id="{!v.YTVVar.videoId}" style="width:100px;height:100px;border-radius:9px;" src="{!v.YTVVar.thumbnails}" /> </div> <div class="slds-media__body"> <p><a>{!v.YTVVar.title}</a></p> <p class="slds-truncate">{!v.YTVVar.Description }</p> <ul class="slds-list--horizontal slds-text-body--small"> <li class="slds-list__item slds-m-right--large"> <dl class="slds-dl--inline"> <dt class="slds-dl--inline__label">By:</dt> <dd class="slds-dl--inline__detail">{!v.YTVVar.channelTitle }</dd> </dl> </li> <li class="slds-list__item"> <dl class="slds-dl--inline"> <dt class="slds-dl--inline__label">Date:</dt> <dd class="slds-dl--inline__detail">{!v.YTVVar.publishedAt }</dd> </dl> </li> </ul> </div> </div> </div> </div> </li>
7. YouTubeViewPortContoller.js
This is controller of YouTubeViewPort.cmp. In this, we will learn how can we pass values from child component to parent component. Whenever YouTube video’s link is clicked that time it will set value in “ChildViewIt” attribute and using this attribute, value will pass to “ParentviewIt” and after this iframe will be shown up with video.
({ //Use for set value src of iframe seeVideo : function(cmp, event, helper) { cmp.set("v.ChildViewIt", "https://www.youtube.com/embed/"+cmp.get("v.YTVVar.videoId") ) ; document.getElementById("youtubeframe").style.display = 'block'; } })
We have almost done our functionality. Now we are going to setup for salesfroce1 app.
C. Create a lightning component tab for salesforce1 :
1. Go to setup menu
2. Go to Create –> Tab –> Create Lightning Component Tabs
3. Fill Values here :
4. After creating tab Go to Mobile Administration –> Mobile Navigation
5. Here move YouTube tab to selected list.
All Setup ???
Happy Coding…
Hi Vishnu,
http://www.googleapis.com is not available. It says Not Found. I tried same to implement in one of my dev org. It is not working. Can you please help me to achieve this. Thanks in advance.
LikeLike
Hi,
We can’t open this link directly. This is an endpoint. Like when we make our query then it will look like:
https://www.googleapis.com/youtube/v3/search?part=snippet&maxResults=20&q=salesforce&type=video&key=AIzaSyC60-a9ziN9zLIcb9ueYv2-IwS03CnYgI4
To access this, we need to fill all data in API.
LikeLike
I am getting many errors in this code
LikeLike
Hi Lokesh, The code is around 3 years old. You may have to dig and fix the errors.
LikeLike