2

I am trying to make a tabbed windowing system within a webpage using om-bootstrap's "pills" navigation by adding tabs when links get clicked and removing tabs when an X button on the tabs is clicked.

I need to know how to add and remove data from the global state/store and create a macro that can be used to declare a tab app component and make it remove itself when it is no longer alive.

What is the best way to reference the global state? How can I make a component remove/unmount itself when it gets closed?

user2491
  • 83
  • 4

1 Answers1

0

Since removal of a subcomponent affects its owner, you should let the owner (i. e. the "tab system") know that this tab needs to be closed/destroyed/obliterated.

I've digged through todomvc example (live) assuming your process of destroying tab panes is pretty much the same as destruction of TODO items there. I see nothing ocnflicting so far. Here are my findings:

  1. A channel is used.... When application starts (IWillMount), a (chan) (from core.async) is written into application state at :comm key.
  2. ...for event handling.... Events from the channel are handled in the loop following that code, in go-form, asynchronously with the block it appears in (with <! being a "kinda blocking" operation). Well, you may know it, I didn't, still learning what is CLJS all about.
  3. ...that is passed to all child items' init states.... So it becomes a way for children to send events to the root. I'm starting to like this.
  4. ...so they can send events to their parent! This is done in put! calls with the comm channel, fetched in the linked line. Events put there are handled by the loop defined in (2), which delegates them to appropriate functions depending on type (accompanying keyword).

I'm nowhere near a ClojureScript pro, but I'm learning. So if the above doesn't make sense, this is normal and means I didn't understand something. If that turns out to be the case, putting me back on track would be much appreciated.

D-side
  • 9,150
  • 3
  • 28
  • 44
  • That is a great example of removing components and communication - clearly components are being destroyed. However, you have only explained the communication. It seems much more complex operations are at play. Take a look at [util.cljs](https://github.com/swannodette/todomvc/blob/gh-pages/labs/architecture-examples/om/src/todomvc/utils.cljs), it includes goog.ui IdGenerator into a guid function used in [app.cljs](https://github.com/swannodette/todomvc/blob/gh-pages/labs/architecture-examples/om/src/todomvc/app.cljs#L94). – user2491 Jul 15 '15 at 15:50
  • @user2491 I fail to see the relevance of this to component removal. On top of that, `(guid)` is only used once outside of benchmarks and it does what its name says. – D-side Jul 15 '15 at 16:01
  • You may be right as I am not an expert by any means either, but it seems core.async is not necessary at all for component removal and that it is actually done [here](https://github.com/swannodette/todomvc/blob/gh-pages/labs/architecture-examples/om/src/todomvc/app.cljs#L142) somehow by adding and removing unique ids for each child-component. For example, I should be able to have "delete random child" button on the parent and not have any communication – user2491 Jul 15 '15 at 16:24
  • @user2491 No, not for removal. I was looking at how a child can self-destruct. Best I could think of is telling the parent "kill me", TODOMVC uses a channel for that. And the parent does that [here](https://github.com/swannodette/todomvc/blob/gh-pages/labs/architecture-examples/om/src/todomvc/app.cljs#L103). `om/transact!` is defined [here](https://github.com/omcljs/om/blob/245d5b0a5837593e412f31c1eb2ac376b8ffa7b7/src/om/core.cljs#L1224): just modifies the state tree and triggers a re-render. – D-side Jul 15 '15 at 16:37
  • `tag` seems to be just a "unique transaction key" and only contains descriptive information on what it does. No ides what is it for, but it seems to not be compulsory. – D-side Jul 15 '15 at 16:38