SPFx. Client Web Part Property Pane Dependent Properties. Part III: Styling Dependent Properties Control as Office UI Fabric dropdowns. Knockout version.
This is the last post of three that explain how to add dependent properties to Client Web Part Property Pane. As an example of such properties I decided to use Lists dropdown and Views dropdown. Views dropdown is populated based on selected List. As a result of these three posts we'll have a fully working web part with ability to select List View in Property Pane:
SPFx. Client Web Part Property Pane Dependent Properties. Part III: Styling Dependent Properties Control as Office UI Fabric dropdowns. Knockout version. (current post)
All the code is available on GitHub (https://github.com/AJIXuMuK/SPFx/tree/master/dep-props-custom-class) I'm using Visual Studio Code IDE for the tutorial. This post describes creation of custom Knockout bindings, custom Knockout components and styling your components in Office UI Fabric manner.
In previous post we created a custom field that consists of two dependent dropdowns. Everything works good but looks not so good. It would be much better if our dropdowns look similar to Office UI Fabric Dropdown. Unfortunately there is no Knockout version of Office UI Fabric Dropdown and a Dropdown from Fabric JS is pretty static - it creates <ul> markup based on a <select>. But if you change something in your select dynamically it won't reflect UL until you recreate the Fabric JS dropdown. So let's create our own Knockout.js component styled as Office UI Fabric Dropdown. You can find documentation on Knockout components here so I won't spend time to describe it deeply. In few words we need to create a view, a viewmodel and register the component to be able to use it in our app. First of all, we need to create some interface that will describe a single dropdown item. We need value, text and selected flag to describe an item (/webparts/depProps/components/dropdown/viewmodel):
It also would be great if our component's bindings look similar to standard <select> bindings. It means that we could provide
options - observable array of dropdown items
optionsCaption - dummy option to prefix a list of dropdown items
value - selected value
disabled - flag if a dropdown disabled or not
in a manner like
Based on the above we can create an interface that describes parameters of our component (/webparts/depProps/components/dropdown/viewmodel):
Now let's look at Office UI Fabric Dropdown markup to understand what we need to implement in our component's view:
This is how our view should look. LI elements will be created dynamically based on options property. The only thing we need to decide is how to implement inserting of optionsCaption dummy item before options in the dropdown. There are two ways for that. First one is to implement the logic in viewmodel: get options array and insert a new element there which will have optionsText as text, -1 as value. And in the view we can use simple for binding to iterate through the items and create li elements for each of them. Second one is to create a custom binding similar to out-of-the-box options binding. I selected the second option to practice in custom bindings. Let's call the binding class as MsDropdownOptions and put it in /webparts/depProps/bindings/MsDropdownOptions.ts:
Also we need to register this binding inside knockout. For that we need to extend KnockoutBindingHandlers interface definition with a new property (/webparts/depProps/bindings/bindings.d.ts):
And also we'll create a function that will register our custom binding (/webparts/depProps/bindings/MsDropdownOptions.ts):
Now we can use this binging in our view. So the final markup with bindings (based on Office UI Fabric Dropdown markup) will look like (/webparts/depProps/components/dropdown/view.ts):
msoptions, optionsCaption and itemSelected parameters are handled inside created custom binding.
As you can see there are some methods in the binding (onOpenDropdown, onItemSelected, isOpen, disabled). All these methods should be implemented in a viewmodel. So let's create the viewmodel (/webpars/depProps/components/dropdown/viewmodel.ts).
Now register it (/webparts/depProps/components/dropdown/Dropdown.ts):
And finally use it in our custom Property Pane field. For that:
import component name in PropertyPaneViewSelectorView.ts
change the _template variable of PropertyPaneViewSelectorView class to:
and change PropertyPaneViewSelector class to register the component in constructor:
Now we finished and can enjoy our beautiful custom Property Pane Field with Office UI Fabric-like dropdowns: Let me know if you have any questions or comments.
Comments