Feather: Create a List widget
The following tutorial demonstrates how to create a simple MVC List widget based on the Feather UI framework. The List widget displays a list of items on the frontend and provides functionality for configurations via a customized designer. The goal of the current tutorial is to provide an overview on how to create a MVC widget in a separate assembly that uses a custom designer.
Install the List widget
- Clone the feather-samples repository.
- Build the
ListWidget
project.
- Reference the
ListWidget.dll
from your Sitefinity’s web application.
Create the List widget
Feather makes it possible to have MVC widgets that are stored in separate assemblies. The following sample creates the List widget in a separate assembly.
Perform the following:
- Create a new class library and name it ListWidget.
- Install
Telerik.Sitefinity.Feather.Core
NuGet package using the following command:
Install-Package Telerik.Sitefinity.Feather.Core
NOTE: Make sure that you have set the Feather package source as explained in Feather: Get started
- Modify the
AssemblyInfo.cs
of the ListWidget
by adding
using Telerik.Sitefinity.Frontend.Mvc.Infrastructure.Controllers.Attributes;
[assembly: ControllerContainer]
- Create the following folders:
MVC
MVC\Views
MVC\Views\List
MVC\Controllers
- In the context menu of
ListWidget
code library, add a new enum
, name it ListMode, and add its declaration in the following way:
public enum ListMode
{
Numbers,
Bullets
}
Create the controller
Perform the following:
- In folder
MVC/Controllers
, create a new class that derives from the System.Web.Mvc.Controller
class and name it ListController.
- Add the following properties to the
ListController
class:
- Create an
Index
action that passes the title of the list, the type of the list, and the list items to the Index
view of the List widget.
To pass the required information to the view, you can use the ViewBag
property of the controller class. You can use the following code sample:
public ActionResult Index()
{
this.ViewBag.ListTitle = this.ListTitle;
this.ViewBag.ListType = this.ListType;
this.ViewBag.ListItems = this.DeserializeItems();
return this.View();
}
private IList<
string
> DeserializeItems()
{
var serializer = new JavaScriptSerializer();
IList<
string
> items = new List<
string
>();
if (!string.IsNullOrEmpty(this.ListItems))
items = serializer.Deserialize<
IList
<string>>(this.ListItems);
return items;
}
NOTE: To resolve the JavaScriptSerializer
class, you must add a reference to System.Web.Extensions
assembly
- Add the
ControllerToolboxItem
attribute to the ListController
class.
This way Sitefinity CMS automatically adds the List widget in the toolbox.
The following code demonstrates how to use the ControllerToolboxItem
attribute:
[ControllerToolboxItem(Name = "SampleList", SectionName = "Feather samples", Title = "Sample List")]
Create the views
You need to create an Index view, because this is the only view that is used by the ListController
. To do this, you must create a new Razor view named Index and to place it in the MVC/Views/List folder.
To create the Index view, use the following code:
<
div
class
=
"sfContentBlock"
>
@{
string openingTag;
string closingTag;
if (ViewBag.ListType == ListWidget.ListMode.Bullets)
{
openingTag = "<
ul
>";
closingTag = "</
ul
>";
}
else
{
openingTag = "<
ol
>";
closingTag = "</
ol
>";
}
<
h2
>
@ViewBag.ListTitle
</
h2
>
@Html.Raw(openingTag)
foreach (var listItem in ViewBag.ListItems)
{
<
li
>@listItem</
li
>
}
@Html.Raw(closingTag)
}
</
div
>
NOTE: You can create a Razor view in a class library project by selecting HTML Page from the Add New Item dialog, and then renaming the file extension to .cshtml
. In the file properties, set the view as Embedded Resource.
Customize the widget designer
Feather provides widget designer created using ASP.NET MVC, AngularJS, and Bootstrap framework. When a MVC widget is registered in the toolbox, Feather will automatically open for you the new MVC designer. This way you can edit the public properties of the widget though the designer without any additional configuration.
In addition to the default property editor view, you can add your custom views inside the widget designer. This way, you can show different editing options or more complex UI.
This tutorial demonstrates how to modify the MVC designer by adding two views to it – the Settings view and the Manage items view. The Settings view provides options for customizing the visual appearance of the items on your page, while the Manage items view provides simple UI for adding and deleting items from the list.
Add a custom view
Customizing the outlook of the MVC designer that is associated with your custom widget does not require any specific configuration. You do it by following a naming convention. To add a custom view to the MVC designer, you must use the following rules:
- The name of the custom view file must start with
DesignerView
,
For example, DesignerView.<ViewName>.cshtml
- The custom view file must be physically located in folder
Views
that is associated with your widget.
For example, in Mvc/Views/<ControllerName>
- The custom view file must be marked as embedded resource.
This way Feather will automatically recognize the custom designer view and will generate a button for this view in the widget designer. Feather creates an Angular controller for your custom designer view and populates its scope with all the properties of the widget. Inside your custom designer view you can bind html
elements to the properties of the widget by using the ng-model
attribute.
For example, to bind an input html
element to a property of your widget, you should add the ng-model
attribute to the input html
element and set the value of the ng-model
attribute to be equal to properties.<Your property name>.PropertyValue
. This way you are taking advantage of the two way binding functionality that AngularJS provides.
Create the Settings view
To create a Settings view for the List widget designer, perform the following:
- Inside folder
Mvc/Views/List
, create a new Razor view and name it DesignerView.Settings.cshtml.
- Set the newly created file as Embedded Resource.
- To add the ability to specify the title of the List widget via the Settings view, in the
DesignerView.Settings.cshtml
, place the following code:
<
label
>List title</
label
>
<
input
id
=
"list-title"
ng-model
=
"properties.ListTitle.PropertyValue"
type
=
"text"
/>
NOTE: You can also easily modify properties of custom types.
-
To add a UI elements through which you can control the value of the
ListType
property, use the following code:
<
label
class
=
"radio"
>
<
input
type
=
"radio"
ng-model
=
"properties.ListType.PropertyValue"
value
=
"@ListWidget.ListMode.Numbers"
>
Numbers
</
label
>
<
label
class
=
"radio"
>
<
input
type
=
"radio"
ng-model
=
"properties.ListType.PropertyValue"
value
=
"@ListWidget.ListMode.Bullets"
>
Bullets
</
label
>
When you open the designer of the List widget you can see a new Settings button at the bottom-right corner. By clicking the button, you load a designer for editing the widget properties that is created without using JavaScript.
Create the Manage items view
In order to meet specific business requirements, you may need to implement a complex UI logic in the widget designer. Feather provides a way for building custom views that contain heavy client-side logic.
Use this tutorial to create a Manage Items view that will contain a more complex client-side logic for manipulating the value of the ListItems
property of the List widget.
Perform the following:
- In folder
Mvc/Scripts/List
, create a new JavaScript file and name it designerview-manageitems.js
- In the created file, define a custom Angular controller.
By using Angular controllers you have a single place where you can define the client-side business logic that is associated with your custom designer view.
NOTE: If you do not provide a custom Angular controller, the default one will be used.
- Name the controller by concatenating the name of the designer view associated with it and the
Ctrl
suffix.
In this example, name the controller ManageItemsCtrl.
- Register the
ManageItemsCtrl
controller in the designer module.
- Specify that it the depends on the
$scope
and the propertyService
.
The $scope
is an object that refers to the application model and that is part of the Angular API. The propertyService
is custom Angular service created in Feather that provides functionality for working with the properties of the widget.
- In the custom
ManageItemsCtrl
controller, retrieve the values of the widget properties and populate them into the scope.
Use the following code:
designerModule.controller('ManageItemsCtrl', ['$scope', 'propertyService', function ($scope, propertyService) {
$scope.feedback.showLoadingIndicator = true;
//Makes call to the controlPropertyService to get the properties for the widgets.
propertyService.get()
.then(function (data) {
if (data) {
$scope.properties = propertyService.toAssociativeArray(data.Items);
$scope.listItems = $.parseJSON($scope.properties.ListItems.PropertyValue);
}
},
function (data) {
$scope.feedback.showError = true;
if (data)
$scope.feedback.errorMessage = data.Detail;
})
.finally(function () {
$scope.feedback.showLoadingIndicator = false;
});
In the scope of the ManageItemsCtrl we added two methods for managing the items:
$scope.newListItem = "";
//Adds item to list. $scope.addListItem = function () {
$scope.listItems.push($scope.newListItem);
$scope.properties.ListItems.PropertyValue = JSON.stringify($scope.listItems);
$scope.newListItem = "";
};
//Deletes the selected item from the list. $scope.deleteListItem = function (index) {
$scope.listItems.splice(index, 1);
$scope.properties.ListItems.PropertyValue = JSON.stringify($scope.listItems);
};
In the above functions, you update the $scope.properties.ListItems
depending of the action that the user takes. This way, when the user clicks Save, Feather automatically saves the updated values of the widget properties. If the user clicks Cancel, Feather discards the changes applied on $scope.properties
.
Change the default view of the designer
By default, when you open the designer of a widget, Feather automatically displays a default designer view. You can modify this behavior through a JSON config file. By specifying the default view for a designer, the JSON config file provides a way for configuring the behavior of the MVC designer and also serves as a container for registering the client-side dependencies of the designer, such as the required JavaScript files.
In this tutorial, you specify the Manage Items view as the view that is displayed when you open the designer of the List widget.
To do this, perform the following:
- In folder
Mvc/Views/List
, create a DesignerView.ManageItems.json file and set it as Embedded Resource.
- Specify the default view for the designer by adding the following code:
- Build the project and test the result by dragging the List widget on a page.