Sitecore SPEAK 2.0 CRUD operation part 2 – List component & Query Datasource

In this part we will see the operations like Listing & Delete in a Speak application. What i am doing here? I first wanted to create a form to save the data. If so, visit the first part here https://pratiksatikunvar.wordpress.com/2017/08/30/sitecore-speak-2-0-crud-operation-part-1-form-component. We will walk through ListControl & QueryDataSource in detail to complete the exercise along with binding complex (DropLink) field.

Create a blank SPEAK application

We already seen how to create a speak page using the branch template DashboardPage for 2.0 version in previous blog post. Let’s follow the same steps and create a page under /sitecore/client/Your Apps/DemoApp We will call it Departments for our exercise.

Let’s quickly move towards working with ListControl & QueryDataSource to list all the departments created.

Add a ListControl component

  1. From the design layout, add new rendering. Search with ListControl and you will be able to see it as:
    00
  2. Set the Id property to ListDepartment for this example.
  3. In our example, we wanted to bind the department items created in repository in master database. For ex: /sitecore/content/Home/Repository/Departments. All items having Department Name field set to respective department name.
  4. Let’s use QueryDataSource to read all these departments. Open design layout of FormPage and add QueryDataSource component.
    10
  5. Properties which are most important in QueryDataSource are Database and Query. Database – Specifies the name of the database. You can use $context_database, $context_contentdatabase, or a literal name. Query – Specifies a Sitecore Query or a Sitecore Fast Query.
    11
    Specify master in Database and /sitecore/content/Home/Repository/Departments/* in Query as shown above.
  6. Now bind this data to the ListDepartment added above in DynamicData property
    01
  7. Now let’s visit the Departments speak page in browser and see how it looks like
    02
    No data? Let’s confirm by checking the Network tab. As QueryDataSource will call the item API to fetch the data03
    We are getting 3 items. Than why ListControl not showing anything. Let’s first define what we wanted to display in list. I wanted to display Id & Department Name. Let’s create the columns for each and let ListControl know.
  8. Create a folder under /DemoApp/Departments/PageSettings/ named Columns where we will add two columns. From Design Layout add new item and search with ColumnField and you will have a list of templates based on which you can create columns.
    05
  9. We will add columns of type ColumnFieldText.
    04
  10. Specify ColumnTitle & DataFieldName for both the columns.
    For Id column, set the DataFieldName to Id and
    For Name column, set the DataFieldName to Department Name.
    And specify the item Ids of both the columns in ColumnDefinitionItems property of ListControl separated by pipe(|).
    06
  11. I think we have done all the things to list the data in ListControl. Let’s just revisit the page to see if it’s working or not.
    07
    It’s not working. We can only see the header but no data. I checked browser console and found the below error.
    08
    I couldn’t get clear idea what is the real issue here. I tried to remove column Id and it started showing the Department Name. Than i realized that for standard fields like Id, Name, DisplayName we have to specify it in special manner.

    1. itemId (the item ID)
    2. itemName (the item name)
    3. $displayName (the display name)
    4. $database (name of the database the item belongs to)
    5. $language (the language of the item)
    6. $version (the version of the item)
    7. $templateName (the name of the template the item is based on)
    8. $templateId(the item ID of this template)
    9. $hasChildren (shows whether the item has child items or not)
    10. $path (the Sitecore path of the item)
    11. $url (the Sitecore URL of the item)
    12. $mediaurl (the Sitecore URL of the icon asset of the item)
    13. $icon (the Sitecore path of the icon of the item)

     

  12. So, i specified $itemId into the DataFieldName for Id column and everything worked fine.
    09
  13. As we know now that QueryDataSource uses item API to get the data, It returns all the data of the item. Which is sometime huge call if number of item we are getting is large. In this case Fields property of QueryDataSource comes handy. You can specify the name of fields you wanted to retrieve separated by pipe (|).
    10

Important: Showing complex fields

We got to see the departments listed (Yay). But consider a scenario if Department item what we are retrieving has a ComplexType field say SubDepartment of type DropLink which points to another Department item. When we get the data using QueryDataSource than we gets the ItemId (which is raw value) in SubDepartment field value but we want Name of that SubDepartment.

How to display information from that referenced item based on item id?

  1. Well that is really complex. I spent a good amount of time. But there isn’t a simpler way around ListControl & QueryDataSource/SearchDataSource. One option is to implement the EntityDataSource. Where you creates the controller based on ServiceApiController. Implement Action method. Retrieve the data in a way you want and return the EntityDataModel back. But that’s sounds like a lots of work.
  2. For a simple solution, we do have another option. Mostly we may like to show the Name of that referenced item into the list. So, if that is the requirement than we can easily get the DisplayName of the item referred based on ItemId. QueryDataSource has the property named Formatting. Where you can specify predefined rules. For ex: $convert_date_to_friendly_format: convert internal date format to localized format $send_localized_dates: send localized versions of all dates
    $convert_id_to_display_name: convert item IDs to the display names of the items
    You can enter multiple formats as a pipe-separated (“|”) list.
  3. $convert_id_to_display_name is what we needed. Specify this to the Formatting property. And now when we access the SubDepartment property in ColumnField, It will display DisplayName of that item instead of ItemId.
    11
    12

If we could also have more control over methods/events than we could achieve such solutions very easily. But unfortunately we do not have that luxury in Speak.

Delete a record

  1. We will required to add a Delete button to the ListControl in order to delete the record. From Design Layout, add the item of type FormFieldTemplate to the Columns folder we created. We will call it Action for this example.
  2. FormFieldTemplate is used when you wanted to specify the html yourself for the column. It has an important property called HtmlTemplate. Where we can specify the custom html for the column. In our case we will specify the anchor tag. We will specify onclick event of the anchor. We will also required to pass the Item Id to the javascript function. So, that we could delete that item. Note: Do not forget to specify item id of the Action item to ColumnDefinitionItems property of ListControl to make that visible in listing. So, our Action column’s HtmlTemplate will look something like
    13
    Where, deleteDepartment will be a JavaScript function in PageCode (Don’t know about PageCode? See previous blog post). You can freely use any fields from the retrieved items using QueryDataSource in HTML template.
  3. Final View
    14

I hope the tutorials were helpful and by referring these posts one can able to achieve Listing & Form page in Speak without any trouble.

Keep SPEAKing Sitecore!

Advertisements

Sitecore SPEAK 2.0 CRUD operation part 1 – Form component

I have worked on several Speak application through out different projects. But all used to be simple having date range and a submit button which upon clicking exports the data to excel format. But this time i had to create a little complex form having many form fields. There are many good blogs available. For ex: Speak for newbies by @mhwelander https://mhwelander.net/2014/06/27/speak-for-newbies-part-1-creating-a-new-application, Google map speak component by @gorhal https://visionsincode.wordpress.com/2015/08/06/make-a-google-map-speak-component-in-sitecore, and many more.

In Sitecore SPEAK 2.0 we do have a guidance dashboard at /sitecore/client/Business Component Library/version 2/Content/Guidance/Dashboard which lists all the Speak components and minimum useful properties (Yes, only minimum, not all). I was about to start with the normal approach as i followed earlier and mentioned in blog https://mhwelander.net/2014/07/03/speak-for-newbies-part-5-building-a-custom-form-3/ by generating layout using row/column and adding required components like textbox, datetime to the speak layout. But from guidance dashboard, I saw Forms section and thought to give it a try. In my surprise, I found it lot more aligned and proper way to implement a form in speak application. So, we will be seeing how to create a simple/complex form in Speak application using Form component.

Create a blank SPEAK application

  1. Create a folder under /sitecore/client/Your Apps with your application name (Of course not to forget in Core database). All the pages and resources related to your app will reside inside that folder. You can use Sitecore Rocks for this purpose. For this example we will call it DemoApp.
  2. Create a page for building a form. You can choose from default provided branch templates for v1 version.
    01
    For Speak 2.0, there isn’t any default branch template available. But one of community member LukasSkowronski has created such and you can get it from https://marketplace.sitecore.net/Modules/S/SPEAK_20_Branches.aspx. After installing the above module, you will find a DashboardPage branch template for v2 as well. Go ahead and create a page using that branch template in our DemoApp folder. In our case we will call it FormPage.
    02
  3. When you see the design layout (right click on page -> commandy -> Design Layout), It will look something like this
    03
  4. Let’s view our application’s form page into browser from http://{Host}/sitecore/client/Your Apps/DemoApp/FormPage
    04
    Select UseFullWidth checkbox from FormPage item to view it in full width. Set the required property/field like Browser Title etc.
  5. We are ready to move to something complex (Yes. Form). We are not getting in detail for basics like PageCode, Navigation, Breadcrumb etc.

Add a Form component

  1. From the design layout, add new rendering. Search with form and you will be able to see Form component as:
    05
  2. Set the Id property to DemoForm for this example. CellAttributes, LayoutType and UseCellBottomPadding these are the properties to make change in layout of the form. See {Host}/sitecore/client/Business Component Library/version 2/Content/Guidance/Dashboard?componentId={59E2A66D-11D2-488D-A3BC-6C1C81326645}&menuItemId={83C20D87-4958-4A29-89FD-1D6BF41D6BFB} for more information.
  3. Create a folder under /FormPage/PageSettings/ called FormElements. We will be adding all the form elements inside the folder. Select the Item Id of that folder and specify it to StaticData property of Form component as shown
    06
    With this, Form component will able to know from where to pick form elements.
  4. Now, lets start adding fields to form. For demo purpose we will be adding one Simple (Textbox) another Complex(Dropdown with Dynamic Data).
  5. Right click on the FormElements folder, add new item, search with Form. You can add all that item having Form Parameters. For ex: FormImage Parameters, FormTextbox Parameters etc.
    07
    We will first select the FormTextBox Parameters. We will name it SimpleType for this example.
  6. Open newly created form element. You will find few properties useful. Set those properties and visit the FormPage again so you will have the idea of which property is being used where.
    08
    09
  7. Now add the another form element of type FormDropList Parameters (Complex). Lets name it Department. What’s complex here? You can provide either static data or dynamic data to the DropList. In static data, you creates the items based on specific parameters in Core database and select root item in StaticData property. While in DynamicData, you’ll have lots of option. For ex: SearchDataSource, QueryDatasource, EntityDataSource etc. Where all these DataSource gets the required data for you and you’ll bind those data to DropList. We will see DynamicData in this example. Select the HelpText and FormLabel properties and leave all data related properties blank for now.
  8. In our example, we wanted to bind the department items created in repository in master database. For ex: /sitecore/content/Home/Repository/Departments. All items having Department Name field set to respective department name.
  9. Let’s use QueryDataSource to read all these departments. Open design layout of FormPage and add QueryDataSource component.
    10
  10. Properties which are most important in QueryDataSource are Database and Query. Database – Specifies the name of the database. You can use $context_database, $context_contentdatabase, or a literal name. Query – Specifies a Sitecore Query or a Sitecore Fast Query.
    11
    Specify master in Database and /sitecore/content/Home/Repository/Departments/* in Query as shown above.
  11. Now we have data available to bind to DropList through QueryDataSource. To bind this data to DropList, specify properties like DynamicData, ValueFieldName, and DisplayFieldName to the DropList element we created.
    12
    DynamicData –  will ensure from where to pic data. In our case it is the items of the QueryDataSource. DisplayFieldName – Name of the field you wanted to display as DropList option text from the Department item. ValueFieldName – Name of the field you wanted to display as DropList option value ($itemId –  what is that? We will see in next blog post). Once done, visit the formpage and you will find the DropList is now filled with the Departments.
    13
  12. As we have added both Simple and Complex form elements into form, let’s add a button to save the data. Add item of type Button Parameters of 2.0 version into FormElements folder where we have added rest of the two elements above.
    14
    Specify the Id and the relevant Text. Specify the name of the JavaScript function you wanted to call on click of the button to save the data in Click property. We will see about that below.
    We are now done with the configuration. Now we need to write some code to save the data. Let’s do that.

Add a PageCode

Easiest way to write the custom code in the Speak application is to create a PageCode (JavaScript) file and refer it to the speak page (in our case FormPage). Let’s perform this step by step.

  1. First thing first. Create a stand alone MVC project as we do not directly work with Sitecore website folder as per standards. You can create empty projects based on Helix structure in VS using the extension https://marketplace.visualstudio.com/items?itemName=AndersLaublaubplusco.SitecoreHelixVisualStudioTemplates by @AndersLaub
  2. Create a folder structure to add JavaScript file inside /sitecore/shell/client as shown
    15
  3. Right click DemoApp, Add new item of type PageCode as shown
    16
    Note: Please ignore that all options showing two times.
  4. Publish the JavaScript file to website folder.
  5. Now, file is present there in the website folder but we will require to map it to the Speak Page. You can do that by specifying path of the JavaScript file in PageCodeScriptFileName property of PageCode component as shown
    17
  6. Now, add a JavaScript function which we have specified in Click property of Submit button form element.
    define(["sitecore"], function (Sitecore) {
      var SaveDepartment = Sitecore.Definitions.App.extend({
          initialized: function () {
              var id = this.getID("departmentId");
              if (id != null) {
                  this.getFormValue(id);
              }
          },
          getID: function (param) {
              var id = Sitecore.Helpers.url.getQueryParameters(window.location.href)[param];
              if (Sitecore.Helpers.id.isId(id)) {
                  return id;
              }
          },
          getFormValue: function (id) {
              var app = this;
    
              jQuery.ajax({
                  type: "GET",
                  dataType: "json",
                  url: "/api/sitecore/Controller/Action",
                  data: { 'departmentId': id },
                  cache: false,
                  success: function (data) {
                      if (data != null) {
                          app.DemoForm.Email.Value = data.Email;
                          app.DemoForm.Department.Value = data.DepartmentId;
                      }
                  },
                  error: function () {
                      console.log("There was an error. Try again please!");
                  }
              });
          },
          saveFormValue: function () {
              var app = this;
              var id = app.getID("departmentId");
    
              var formData = {
                  Email: app.DemoForm.Email.Value,
                  Department: app.DemoForm.Department.Value,
                  DepartmentId: id
              };
    
              jQuery.ajax({
                  type: "POST",
                  url: "/api/sitecore/Controller/Action",
                  data: { "formData": JSON.stringify(formData) },
                  success: function (success) {
                      //Do something
                  },
                  error: function () {
                      console.log("There was an error. Try again please!");
                  }
              });
    
          }
      });
    
      return SaveDepartment;
    });
    
  7. Important thing to note is how you can access the form elements. You can access it using app.{FormElementId}.{ElementId}.value. In our case if we wanted to access the Email element of form DemoForm than we can do it as app.DemoForm.Email.value. Make sure that you specify the Id field of each element and you can access the element using that Id not by name of the element item. Also there are other methods related to form specified in guidance dashboard mentioned in the beginning. Those are getFormData() & setFormData(). Howevwer, I couldn’t make it working. Feel free to play around that.

Finally. We have been able to create a complex form and able to perform operations like Insert/Update. In the coming post, we will be seeing the List & Delete operations.

SPEAK Sitecore until.