Interaction between Views
Need your Views to talk to each other? Say no more. As this topic has come up quite a few times, let’s go ahead and explore some of the different possibilities for View-to-View interaction/communication.
#1 Using a "manager" object that resides in C++, shared by the Views, and exposed to each of them ByRef.
This is generally considered the most performant approach and a View querying the "View Manager" from a reference in JS usually takes very little time to obtain a fairly simple object/information used in the tests below(e.g. calling viewManager.shouldCreateView("view-name") method from the stored JS viewManager reference).

That way - all Views can access the same data whenever they need to without any back and forth(events, calls) between JS and C++.
However - keep in mind that destroying or moving a C++ object exposed by reference to another location, without notifying the JavaScript universe(and reassigning the ref), will cause undefined behavior when the variable is used by JavaScript. On that basis, it is safer to use std::shared_ptr or std::unique_ptr when a container with dynamic memory will be exposed by reference, because it won’t affect the container’s data and wouldn’t require rebinding.
On another note - you can also use the ExposeAsGlobal method on the View to directly expose the reference to the ViewManager as a global object - e.g. View->ExposeAsGlobal("g_ViewManager", &m_ViewManager); will let you access the g_ViewManager reference globally in JS.
In case you would prefer to keep a specific reference to the object rather than exposing it globally, you can listen for an event in JS that will assign it accordingly:


Finally - note that if an object is exposed by ref, all of its nested objects will be exposed by ref automatically as well, as mentioned on the documentation page(click here). However - this applies only if you're accessing them directly. In our binding system, returning the result of a method by value creates a JavaScript object, which is a copy of the returned type, even if the type is a pointer to something. Furthermore, the copied JavaScript object will not contain information for the exposed methods, and all of its exposed properties will be copies of the actual values in C++ at the time of the JS object's creation. Therefore - returning std::vector<Data> in a method(e.g. as the return type of some method of the ViewManager) will result in making copies, even if the actual returned object is a member of the one exposed by ref. In such cases, to ensure you're returning a reference, you can modify the return type as follows:
- in the definition of the method, wrap the return type as cohtml::ByRefHolder<std::vector<Data>> <<someManagerMethod()>>
- and when returning in the method, wrap the object like return cohtml::ByRef(returnedObject)
This way, the returned object is the actual proxy to the C++ object instead of a JavaScript Object copy.
#2 Using an engine.call on the JS side that will obtain the desired information after querying the engine.
Usually, to obtain the same data as ByRef via an engine.call - it will take significantly more time in that same test, due to the additional overhead from (potentially multiple!) event/call communication(s).
Ultimately, as you might have noticed if you tried this - triggering events from View1 to C++ and then to View2 is much more costly in terms of performance, as expected.
#3 Using a single model on the C++ side that will be created in all Views that need to communicate
There's also the option to use a single object, such as the m_ViewManager in C++, and use it as a model by calling view->CreateModel("sharedModel", &m_SharedModel);
on each View. However, this will also require you to call UpdateWholeModel and SynchornizeModels on each View after every change. This will have a negative impact on the performance as model synchronization can be a heavy operation depending on the number of properties, so isn't usually recommended unless the shared data will be used in data-bind-* HTML attributes(i.e. automatically synchronizing the elements in the UI depending on the shared data).
Naturally, choosing the right approach depends on your use case & specific project requirements, but maybe this can help you get started. Code wisely 🚀
Please sign in to leave a comment.
Comments
0 comments