Feather: Use single content item selectors
When working with Feather widgets and widget designers, you may need to implement selectors for single or multiple items. The following article explains the basic principles of using a single item selector for various items, such as dynamic items, news items, or taxa from a flat taxonomy. Feather selectors use standard Sitefinity CMS services to get the corresponding items, for example, the NewsService to get all created News items. Selectors also set the selected items into the designer properties.
In the following example, you create a News selector.
PREREQUISITES:
You created a Feather List widget with a custom designer view and an AngularJS controller for the widget. For more information, see Feather: Create a List widget.
Use selectors
Selectors are part of the Telerik.Sitefinity.Frontend
assembly. Selectors are implemented as AngularJS directives. T use selectors, you need to:
- Reference the needed scripts in your designer
- Declare a module dependency
- Add the selector in the designer view
Reference the scripts
Feather automatically registers the scripts you need and, if no other designer view with explicitly set priority exists, Feather sets your designer view to priority 1. In case you need to have full control over the scripts that are loaded or you want to set custom priority, you can alternatively create your own DesignerView.<YourView>.json
file. If you have a JSON
file that matches the convention (even if empty), this automatic scripts registration will not occur
In your DesignerView.<YourView>.json
file, add a scripts
array. The content of the file should be similar to:
{
"priority"
: 1,
"scripts"
: [
"Mvc/Scripts/Angular/angular-resource.min.js"
,
"client-components/selectors/common/sf-services.js"
,
"client-components/selectors/news/sf-news-item-service.js"
,
"client-components/selectors/common/sf-selectors.js"
,
"client-components/selectors/common/sf-list-selector.js"
,
"client-components/selectors/news/sf-news-selector.js"
]
}
Declare dependency for selectors module
The selector's directive is defined in an AngularJS module called sf-selectors
. You need to reference the widget designer to this module. For more information on the scripts that you must load, see Feather: List of selectors scripts reference.
Feather automatically finds all AngularJS modules you rely on and references the widget designer to them. In case you rely on custom AngularJS modules or have logic that needs an AngularJS controller, you can create your own designerview-yourview.js
file. If you have a .js
file that matches the convention (even if empty), this automatic modules referencing will not occur.
In the designerview-yourview.js
file, place the following code right before the definition of your custom view controller:
var
designerModule = angular.module(
'designer'
);
angular.module(
'designer'
).requires.push(
'sfSelectors'
);
Add the selector in your designer view
In your DesignerView.YourView.cshtml
file, place the following tag anywhere in the HTML:
<sf-list-selector sf-news-selector />
NOTE: By convention, the selector attribute must be preceded by a sf
prefix, followed by the type of the selector concatenated with a "-
" (dash): sf-news-selector
.
The selector attribute renders the title of the selected item and a button to open the selector dialog.
Get or set the selected item
To get or set the selected item, use the following attributes:
<sf-list-selector sf-news-selector sf-selected-item=
"selectedItem"
sf-selected-item-id=
"selectedId"
/>
In the code above, the sf-selected-item
and sf-selected-item-id
attributes create two-way bindings between the selector's scope and the properties selectedItem
and selectedId
in your custom designer's scope.
You can use both attributes or just one of them, depending on whether you need only the ID of the item or the item itself.
For example, if you know just the ID of an item, you can save it in a scope's property and set the property to the sf-selected-item-id
attribute. When the directive is loaded, it gets the item from Sitefinity's service and sets it in the property that is assigned to the sf-selected-item
attribute.
The following example demonstrates how to bind the selected ID to a property of the widget:
<sf-list-selector sf-news-selector sf-selected-item-id=
"properties.SelectedId.PropertyValue"
/>
You must create the SelectedId
property in the controller of your widget. For example:
public string SelectedId
{
get;
set;
}
If you want to use the sf-selected-item
attribute, you must add a property in your widgets controller:
public string SelectedItem
{
get;
set;
}
Next, you add the following code in the designer's controller:
$scope.$watch(
'properties.SelectedItem.PropertyValue'
,
function
(newValue, oldValue) {
if
(newValue) {
$scope.selectedItem = JSON.parse(newValue);
}
});
$scope.$watch(
'selectedItem'
,
function
(newValue, oldValue) {
if
(newValue) {
$scope.properties.SelectedItem.PropertyValue = JSON.stringify(newValue);
}
});
You can now bind the sf-selected-item
attribute to the selectedItem
property from the designer's scope.
Customize the selector
You can change one of the following:
- The template displayed when the dialog is closed
- The overall selector template
Change the template of the closed dialog
By default, when you close the dialog, you see the title of the selected item and a button to open the dialog. To change this behavior, you must add HTML code between the opening and closing tags of the selector's directive. For example:
<
sf-list-selector
sf-news-selector
sf-selected-item
=
"selectedItem"
>
<
alert
type
=
"danger"
ng-show
=
"showError"
>{{errorMessage}}</
alert
>
<
h1
>My dialog is closed now.</
h1
>
<
div
ng-hide
=
"showError"
>
<
span
ng-bind
=
"selectedItem.Title"
></
span
>
<
span
ng-bind
=
"selectedItem.Id"
></
span
>
<
a
href
=
"{{selectedItem.DetailsViewUrl}}"
>Edit</
a
>
<
button
class
=
"openSelectorBtn"
ng-click
=
"open()"
>Select</
button
>
</
div
>
</
sf-list-selector
>
The HTML code inside the selector's tag is generated with the help of the directive's scope. Thus, you can use the scope's properties selectedItem
, selectedItemId
, showError
, errorMessage
, items
, and filterfilter
.
IMPORTANT: To be able to open the dialog, you must have a button with an openSelectorBtn
class and
an ng-click="open()"
attribute.
Change template of selector
You can replace the whole template of the selector. For example:
<
sf-list-selector
sf-news-selector
sf-template-assembly
=
"SitefinityWebApp"
sf-template-url
=
"templates/custom-selector.html"
/>
In the code above, the sf-template-assembly
specifies the assembly where the template is located. This means you can put the template in any assembly that you want to.
The sf-template-url
specifies the path to the template.
The template is compiled with the scope of the sf-list-selector
directive.
Change the text of buttons
You can change the text for the Select and Change buttons in the selector. For example:
<
sf-list-selector
sf-news-selector
sf-select-button-text
=
"Select news..."
sf-change-button-text
=
"Change news..."
></
sf-list-selector
>
In the code above, the sf-select-button-text
specifies the text for the button that is displayed when no items are selected. The default value for this button is Select
. The sf-change-button-text
specifies the text for the button that is displayed when there items were selected. If not specified, the default value for this button is Change
.