Sitecore SPEAK For Beginners – Part 9 – Getting Data for Custom Component

This is part 9 of the blog series Sitecore SPEAK for beginners.

We will continue from our last post where we used our JobItems rendering parameter to render a static text.

In this post I’ll show how we can get Sitecore jobs as a JSON collection & bind that collection to our jobitems property.


As we have seen previouslySitecore’s Item Web API comes handy when we need to fetch data from Sitecore, so We are going to use it to fetch the Sitecore Jobs.
Let’s start with adding one method in the SitecoreJobsList.js as follow:

initialize: function (options) {
    this._super();
    app = this;
    app.set("jobitems", '');
    app.GetJobs(app);
},
GetJobs: function (app) {
}

Notice that I’m initializing the “jobitems” with the empty value.
This JavaScript function GetJobs(app) takes the app as an argument (remember here app is nothing but our custom component).
We call this GetJobs(app) from initialize function means every time user hit the page this function will be called.

Now let’s use jQuery AJAX & Sitecore’s Item Web API to fetch Sitecore Jobs:

GetJobs: function (app) { 
    jQuery.ajax({
        type: "GET",
        dataType: "json",
        url: "/api/sitecore/SitecoreJobs/GetSitecoreJobs",
        cache: false,
        success: function (data) { 
            app.set("jobitems", data);
        },
        error: function () {
            console.log("There was an error in GetJobs() function!");
        }
     });
 }

Important attribute of this ajax call is the url attribute:
The url attribute in the ajax call starts with “/api/sitecore/” which invokes Sitecore Item Web API call.
The  url attribute also contain the name of the MVC controller (SitecoreJobs in our case) & the name of the method (GetSitecoreJobs here).
That means when this ajax call is invoked, Sitecore Item Web API will look for SitecoreJobs controller & it should have the GetSitecoreJobs() method defined.

If we get the Sitecore Jobs from the Controller, we bind our jobitems to the JSON collection :

success: function (data) { 
    app.set("jobitems", data);
}

If Controller isn’t the term you hear very often, let me help you to understand it.
A Controller (simple C# class) is an important part of the MVC  (Model-View-Controller) framework.
As the name suggests, it control the flow of data from Model (e.g. a C# class representing employee table of some database) to View (think about our view rendering(.cshtml) or the ajax call).
We can have multiple views to represent the same data (Desktop View or Mobile View), our Controller can determine (or control) which view should be served.

I hope I was able to explain the MVC Controller but still if you are not sure, don’t worry about this for now.

We have talked enough about the Controller, but haven’t defined it yet.

It’s time to define our Controller & I will use the SitecoreLearnings.Web project which I created earlier.
I started with creating  a folder called Controllers at the root level & then I defined the SitecoreJobsController.cs inside this folder :

Jobs_Listing_58

[Tip : We need to add the Controller keyword with each Controller class we create(this is why we named it SitecoreJobsController.cs), but while calling the controller we do not postfix the Controller keyword]

This is how my SitecoreJobsController.cs look like:


public class SitecoreJobsController : Controller
{
    /// <summary>
    /// Wrapper class for Sitecore Job object
    /// </summary>
    public class SCJob
    {
        public string JobName { get; set; }
        public string JobStatus { get; set; }
        public string JobQueueTime { get; set; }
        public string JobCategory { get; set; }

        public SCJob(Sitecore.Jobs.Job job)
        {
            JobName = job.Name;
            JobCategory = job.Category;
            JobStatus = job.Status.State.ToString();
            JobQueueTime = job.QueueTime.ToLocalTime().ToString();
        }
    }

    public ActionResult GetSitecoreJobs()
    {
        List<SCJob> listSCJob = new List<SCJob>();

        // Get Sitecore jobs
        var jobs = GetJobs();

        // Convert the Sitecore Job object to SCJob object
        foreach (var job in jobs)
        {
            listSCJob.Add(new SCJob(job));
        }

        return Json(listSCJob, JsonRequestBehavior.AllowGet);
    }

    /// <summary>
    /// Get all running or queued Sitecore jobs & sort them by queue time
    /// </summary>
    /// <returns></returns>
    public List<Sitecore.Jobs.Job> GetJobs()
    {
        List<Sitecore.Jobs.Job> jobs = new List<Sitecore.Jobs.Job>();

        jobs = Sitecore.Jobs.JobManager.GetJobs().Where(i => i.IsDone == false)
               .OrderBy(i => i.QueueTime).ToList();

        return jobs;
    }
}

Here I defined a wrapper class SCJob which has all the properties we would need to render Sitecore Jobs.
This SCJob class has a Constructor which takes Sitecore Job object as parameter.

Our Controller has  the GetSitecoreJobs() method to return the JSON collection of currently running or queued Sitecore Jobs wrapped in SCJob object.

Don’t forget to build the project & copy the DLL to our website’s bin folder.

Now let’s modify our view rendering (SitecoreJobsList,cshtml) as below :


@using Sitecore.Mvc
@using Sitecore.Mvc.Presentation
@using Sitecore.Web.UI.Controls.Common.UserControls
@model RenderingModel
@{
    var rendering = Html.Sitecore().Controls().GetUserControl(Model.Rendering);
    rendering.Class = "sc-listcontrol sc-SitecoreJobs";
    rendering.Requires.Script("client", "SitecoreJobs.js");

    //Rendering parameters
    rendering.GetString("jobitems", "jobitems");

    var htmlAttributes = rendering.HtmlAttributes;
}


<div @htmlAttributes>
    <div>
        <table class=" sc-table sc-table-header table">
            <thead>
                <tr>
                    <th class="sc-table-head">Job Name</th>
                    <th class="sc-table-head">Job Category</th>
                    <th class="sc-table-head">Job Status</th>
                    <th class="sc-table-head">Job Queue Time</th>
                </tr>
            </thead>
        </table>
        <div class="sc-listcontrol-body">
            <table class="sc-table table">
                <tbody data-bind="foreach: jobitems">
                    <tr>
                        <td class="ventilate">
                            <span data-bind="text:JobName"></span>
                        </td>
                        <td class="ventilate">
                            <span data-bind="text:JobCategory"></span>
                        </td>
                        <td class="ventilate">
                            <strong>
                                <span data-bind="text:JobStatus,style:{color:'#00000'}"></span>
                            </strong>
                        </td>
                        <td class="ventilate">
                            <span data-bind="text:JobQueueTime"></span>
                        </td>
                    </tr>
                </tbody>
            </table>
        </div>
    </div>
</div>

I tried to match the look & feel of our component to Sitecore SPEAK’s ListControl component, so I updated the rendering.Class to include sc-listcontrol css class.

rendering.Class = "sc-listcontrol sc-SitecoreJobs";

I also followed the html structure of ListControl component (two html tables, where one is rendering the header row & other renders the data).

Below is the important piece of code where we loop through the jobitems (JSON collection) using the knockout js:


<tbody data-bind="foreach: jobitems">

In the loop we bind the properties (JobName ,Category,Status & Queued Time) of Sitecore Job to the different html tags again using knockout js:


<td class="ventilate">
    <span data-bind="text:JobName"></span>
</td>
<td class="ventilate">
    <span data-bind="text:JobCategory"></span>
</td>
<td class="ventilate">
    <strong>
        <span data-bind="text:JobStatus,style:{color:'#00000'}"></span>
    </strong>
</td>
<td class="ventilate">
    <span data-bind="text:JobQueueTime"></span>
</td>

Enough with the code for now.
Let’s see if we can see the list of running or queued Sitecore Jobs on our SPEAK app’s page.
When I opened the our SPEAK app’s (ViewSitecoreJobs) SitecoreJobsListing page, I can only see the header as below:

Jobs_Listing_59

No jobs?
We may or may not see jobs on our page if we just run the page because the moment we run the page we may or may not have the running or queued Sitecore Jobs.

To ensure that our app works fine I republished content item from root level 🙂 & after refreshing our SPEAK app’s page I can see publishing jobs:

Jobs_Listing_60

If you can see something similar like the above screen, Congratulation  you have done a great job of learning & building this Sitecore SPEAK app.

Enough for today! Stay tuned for more.

Sitecore SPEAK For Beginners blog series:
In part 1  Create SPEAK Application.
In part 2 SPEAK Components.
In part 3 Rendering Parameters.
In part 4 Getting Data.
In part 5 Display The Data.
In part 6 Custom SPEAK Component.
In part 7 Rendering Parameters for Custom Component
In part 8 Initialize & Bind Rending Parameter Using Knockout.js
In part 9 Getting Data For Custom SPEAK Component.

If you any question/suggestion, please write in comments.
You can also connect with me on Twitter.