One of the first things that may hit you as you Yo up your first SPFX project using Knockout, is how strangely the properties work. In a non-framework project it’s nice and simple – everything is in the same class, so you can get your properties with:
However, when using Knockout – or any technique that requires a number of classes / ViewModel – passing properties around suddenly gets a bit trickier. Let’s look at how it’s done in the base template, and then in the next post we’ll look at how we can perhaps make things simpler.
Properties in the Base Template
Properties in the base template work thusly (presuming a web part project called Blank)
Defines variables for any custom properties in your web part. Don’t start thinking that the framework looks at this to determine anything regarding the property panel… it doesn’t. You add any more props you want here:
Properties are defined in the propertyPaneSettings() method. Specifics of how to define properties are covered very well elsewhere, so i’ll not cover that here:
The class utilises your custom properties interface. Local variables are defined in the class, one for each custom property:
In the constructor of the web part it creates a bindings object, which is of type IBlankBindingContext (which is defined in your ViewModel) – which in turn implements your IBlankWebPartProps interface. Simple eh?!?
You’ll need to add any custom properties to be initialised here:
In the constructor, we now set up a knockout subscription to the locally defined variable, and in the callback we fire a change on this _shouter object – passing a string to identify what we’re ‘shouting’ about:
This is called on any property change in the properties panel – so here you’ll need to pass the properties to your view model. The template does this by setting a local knockout observable to the new value – which fires the above subscription… which in turn notifies the subscription in your view model.
The bindings object mentioned above is passed into the view model, which has the shouter object attached to it. A subscription is attached to the shouter for each custom property, and in the call back a local property needs to be set so we can actually use it:
So in short…
A change is made by the user in the properties panel. The value is pushed into the web part properties object, and render() is called, which pushes the new value to the _myProp local variable. A subscription on the local variable fires, and in turn forces a _shouter object to send a custom notification to any subscribers (which are in the view model). The view model subscriptions pick up the new value. The villagers rejoice.
There must be an easier way?
If you’ve got this far, I feel your pain and yes I think there is a simpler way to handle all this. I’ll cover using an EventBus in the next post.
For now – I hope the above helped to explain what’s going on(?!?) in your web part.