Communicating with Knockout components - knockout-components

Is there a way to communicate from the parent viewmodel to a KnockoutJS component?
I have a component that contains a bootstrap modal dialog box, to search for customers and return a selected customer. At present, to make the dialog box appear, I pass an observable boolean from the viewmodel in the component's params attribute. To make the dialog appear I set this to true, which invokes the dialog box. I also pass a callback function in params to return the results.
Here is a fiddle demo which shows the concept: http://jsfiddle.net/Quango/5bxbsLt6/
Passing the observable boolean to invoke the dialog doesn't feel right, but it's the only working solution I have. The only other idea I had was to use ko-postbox to create a publish/subscribe function.
It feels like there should be a way to invoke actions, e.g. component.Show() ?

I think the answer here is that there isn't a better way. To communicate from a parent viewmodel to the component, pass an observable value, and then use that directly or subscribe to changes in the component.
I will put a suggestion on the Knockout github project to consider some form of interface.

Related

Pass Click Event to two components up Vuejs

how could a pass a click event from one component to two parents up.
I have a form with a bottom clear, this form component is in a file filterForm
the filterform component is called in another file called TableView and the tableView component is called in a file called Admin
I want to execute a function inside admin when the button clear is clicked
the button is in the file filterForm
the filterForm is used in TableView
and tableView is used in Admin
this is the function I want to call from Admin to test
I understand that I have to make a click event from fileForm and emit that event to Tableview, but the function is on Admin that contains all the data and methods.
Thanks for your help!
Based on $emit event in Vue.js: https://vuejs.org/guide/components/events.html
When you emit an event like this: $emit('someEvent'), the parent someEvent function will fire (and also you can pass some parameters).
Passing a data or emitting a function so that two parents up listens to your event and get the data will need some chaining.
Fire the event on 1st component and get it in 2nd component and then fire the event in 2nd component to get it in 3rd.
Edit: one of the best practices is to use Vuex(Pinia) as a state management tool to pass or get data in an easier and cleaner way.

Managing Angular 5 layout with a service

In an angular5 application, I have various sections of my page layout that I would like to control through an angular service. For example, I have a sidenav component that displays when a value is set to open, and I would like to be able to toggle it from any component I'd like.
My initial thought was that it would be nice if I could bind the open value to a variable in a LayoutService I would create, and the LayoutService would contain a toggle() method that would toggle the value and cause the sidenav to open/close. I could then inject my LayoutService into any component I'd like and control various parts of my layout.
Any idea whether this is possible and how I could go about doing this? I thought it might be possible using an EventEmitter or something, but I was wondering whether there was a simpler way and I'd rather not use redux.
https://stackblitz.com/edit/angular-lj7gsz
Here's a side-bar you can open and close using simple rxjs objects.
In the side-bar service, I've created a BehaviorSubject that you can pass boolean values to and I also exposed an Observable, which will emit every time a new value is passed to that subject.
By subscribing to that observable (I've used the async pipe to subscribe for me), my side-bar component will know when other components wish to open or close the side-bar. All the other components need to do is inject the service and call the service's open or close methods.
It's not perfect, but I feel it's definitely better than using event emitters as they were never made to be used in services.
Hopefully this is helpful.

Vuejs: shared states between components

I would like to know the best practice for implementing shared states between components in Vuejs.
Imagine situation A: you have a web app that shows a modal. The modal has the boolean state show. This state should change if the modal OK-button is clicked, but also if any part of the background is clicked, and perhaps even on some server pushed state change. Thus the modal should be able to change the state as should the parent app.
Situation B: you have a web app that shows input fields inside different components that share a common data value. If the user changes value through the field in one component, it should also update in the other. Again both should even update on a server push event.
Questions:
I am right that the correct way to go about this would be to use vuex and make the shared state a store field that is observed by and changed through emitted actions by all components / parents that need to modify that value?
Does that not introduce this kind of dangerous (since hard to handle) magic reactivity that we know from Meteor?
How to best document the flow, what depends on what?
A: For a modal component, I'd say that show should be a prop. So the parent component can control the modal whatever it wants. In this case there is no shared state at all.
The modal itself doesn't need to know anything about the server. If the prop show is true, just display the modal and vice versa.
I think the mask layer is a part of the modal, so when the mask is clicked, the modal emits an event. The parent component receives the event and can decide to hide the modal or not to.
Vue has an official modal example here (thanks #craig_h for mentioning): https://v2.vuejs.org/v2/examples/modal.html
B: Just bind the vuex state to the inputs. Nothing wrong.
Note that not all the components need to access the vuex store directly. For some pure UI components, just use props. So the parent components have the right to control them and increase flexibility.
I recommend you to read these docs:
https://facebook.github.io/react/docs/lifting-state-up.html
https://medium.com/#dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0#.j7ry4a3as
http://redux.js.org/docs/basics/UsageWithReact.html
Yes these are React / Redux docs. Since Vue is relatively young, react community has more documentation / articles. But both Vue and React are component-based libraries. The idea of how you design a component is basically the same.
You can also take a look at this vuex example: https://github.com/vuejs/vuex/tree/dev/examples/chat
This is a very simple example but it does use all the things I mentioned above. Emitting an event, some pure UI components...

The idea of smart and dumb components in Elm

I like React's/Redux' concept of smart and dumb components, where a dumb component does not handle its own state (Dump component does not know anything about the outside world, all it does is triggering an event and displaying value according to its input). This is trivial because all state in handled in one place (main reducer).
In Elm, each component has its own 'update' function (similar to Redux' reducer), so it does not seem trivial to use the same (dumb & smart components pattern).
Is using smart & dump components a good practice in Elm? If so, will I have components without 'update' method? I wonder how will I pass data (props) to my component and how will I trigger events to the parent component.
I will love to hear your thoughts.
The Elm equivalent of a "dumb component" (a.k.a. Presentational, Pure, Skinny component) is simply a function that produces Html:
view : ... -> Html
The elm-html library is written in this style, e.g.,
button : List Attribute -> List Html -> Html
You set the "props" by providing attributes when you call the function. In particular, you register events by supplying handlers in List Attribute:
button
[ onClick addr ClickAction ] -- event handler
[ text "Click me" ] -- child "components"
You'll see this pattern also in other libraries, although the exact types may be different from List Attribute and List Html.
Another Smart/Dumb distinction you can make is between components that return Effects and those that don't. But to answer your question...
Nothing stops you defining actions in a child
type Action
= Submit
| Click
and in the Parent view having
Child.view (Signal.forwardTo address ChildAction) props
(We pass props because there is no model data as such to pass)
but then handling all the actions in the Parent's update:
case action of
ChildAction act ->
case act of
Child.Submit ->
...
Child.Click ->
...
This would be essential anyway if the impact of an Action in Child was to change the state in Parent or some other child of Parent.

Attach/Render RactiveJS component outside of template

I've got an existing SPA that was developed using nested RactiveJS components. Which is great, and offers a ton of flexibility throughout the entire app. Currently I attempting to add in client side routing support using page. My navigation switches out high-level components using simple {{#visible}}{{/visible}} template markup on each component. This is a little troublesome in its current state as it always kicks off a re-render whenever the high-level component becomes visible again.
Is there a way to render a component, for example, called widget, without using the
<widget></widget>
method? I've already "registered" the component with the parent, but obviously when constructing it by means of
new App.components.widget
I am able to control how/when it's rendered/inserted/detached, but lose the recognition in the application's component hierarchy.
There is insert exactly for that. You don't even need to "register" it to the component you plan to put it to. You can use the different find* methods or nodes to easily retrieve a reference of your planned container element.
var instance = new YourDetachedWidget({ ... });
instance.insert('#your-container'); // This could be a node, selector or jQuery object