15

I understand how to use imports: {} and exports: {} to share a UI components properties, such as:

defaults: {
 exports: {
 shouldShowMessage: '${$.component}'
 }
}

Which returns the component name in the exports.

enter image description here

But when I try to export a Knockout observable it is always undefined:

defaults: {
 exports: {
 shouldShowMessage: '${$.shouldShowMessage}'
 }
}
...
setupKoBindings: function() {
 this.shouldShowMessage = ko.observable('Testing');
}

enter image description here

As a workaround I am going to create a storage model as explained here but I would prefer to use the imports and exports.

asked Dec 20, 2017 at 16:25

1 Answer 1

15

The values of the exports object have to resolve to a name and a property of a UiComponent instance, separated by a ':', for example checkout.cart.total:title.
The export target name has to include the UI component "namespace".

In your example, you set the value to a string, which resolves to a property of the UiComponent that is the export source. The export is undefined when you inspect it because that is not a valid export target.

Here is an example that works:

defaults: {
 exportTarget: "foo.bar",
 exportTargetProperty: "showMessage",
 tracks: {
 shouldShowMessage: true
 },
 exports: {
 shouldShowMessage: '${$.exportTarget}:${$.exportTargetProperty}'
 }
}
...

The above will copy the value of the shouldShowMessage property into the property showMessage of a UiComponent with the full name foo.bar every time the value changes.
Note that this will not automatically make the target property a KO observable, too. That has to be declared explicitly, if value changes should trigger KO to rerender DOM nodes that access that property.

By the way, adding shouldShowMessage to the tracks object will make it a ko-es5 observable automagically. Using a literal ko.observable() works, too.

In the example above, the exportTarget and exportTargetProperty are configured in the defaults. They also could be specified as part of the UiComponent options in the JSON, which usually makes more sense, since that is where the UiComponent hierarchy including the UiComponent names are defined.

Finally, I would like to note that I personally think your solution using a value object to pass the value to the other UI component is better than using exports or imports. In my experience keeping shared state in the DOM or in UiComponents is a recipe for spaghetti OOP in all but the simplest cases.

answered Jan 24, 2018 at 17:21
6
  • Excellent explanation, thanks @Vinai! I'll give it a try when I have time and mark this as accepted if it works. Commented Jan 24, 2018 at 17:25
  • I've run into some issues when using tracks, manually subscribing to observables no longer works this.shouldShowMessage.subscribe is not a function when using this.shouldShowMessage.subscribe(function() { ... }); It works fine when setting observables any other way. Feels as though I'm missing a step or tracks doesn't create an observable the same way. Commented Feb 20, 2018 at 9:22
  • 1
    You are right, the properties are no longer regular ko observables, just ES5 getter/setter pairs. If you want to access the original observable function you can inject ko and use ko.getObservable(this, 'shouldShowMessage').subscribe(function(newValue) { ...}); (the first argument is the viewmodel (this), the second one the name of the tracked property. More info here: github.com/SteveSanderson/knockout-es5 Commented Feb 20, 2018 at 11:07
  • Ahh that makes sense, you're the best <3 Commented Feb 20, 2018 at 11:19
  • 1
    After playing around with imports and exports and still failing I agree this is spaghetti code, I've given up and I'll stick with manual subscriptions and a storage model. Commented Feb 22, 2018 at 14:20

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.