cerebral-legacy / cerebral-module-router

An opinionated URL change handler for Cerebral
http://cerebral-website.herokuapp.com/documentation/cerebral-module-router
19 stars 4 forks source link

Only modify queryParams? #96

Open awei01 opened 8 years ago

awei01 commented 8 years ago

Some background is here: https://github.com/cerebral/cerebral-module-router/pull/92

Basic gist: 1) I have a button that toggles a modal window. 2) I want the URL query string param to reflect that a modal window has been opened. 3) The button that toggles the modal window can exist on a variety of different URLs

Currently, there's no way to know what the current signal or route is, so I cannot re-call the same signal and pass query params.

A workaround is to simply do <a href="?modal=MyModal">Open Modal</a> or something, but this circumvents the router altogether.

christianalfoni commented 8 years ago

Hm, this is interesting. I think maybe the cleanest way to solve this is:

Create a signal you call modalChanged, or something:

modules/App/signals/modalChanged.js

export default [
  changeModal // An action which checks for the "input.modal" parameter and set the modal
]

Now, what you is the same strategy as you handle authentication. You just create a factory for your signals to add this chain:

module.addSignals({
  homeClicked: withModal(homeClicked),
  // like authentication is typically, same thing
  homeClicked: authenticated(homeClicked)
})

The factory just composes the modalChanged signal, typically:

function withModal(chain) {
  return modalChanged.concat(chain)
}

You do not have to use a factory, you can also explicitly compose the modalChanged signal into wherever you want it. This might be useful related to async behaviour:

[
  getItems, {
     success: [],
     error: []
  },
  ...modalChanged
]

So here we trigger the modal at the end, but in an other signal you might want it to be first. Need the flexibility I think.

The only missing piece now is how to update the url from changeModal action. We would have to expose a service on the router for this:

function changeModal({input, state, services}) {
  state.set('currentModal', input.modal);
  services.router.addQuery({modal: input.modal});
}

This might open up other possibilities. Adding queries manually could be beneficial in general.

Okay, these are my initial thoughts :)

awei01 commented 8 years ago

Brilliant. Thanks for the insight.

christianalfoni commented 8 years ago

@Guria What do you think? About the addQuery thingy there?

awei01 commented 8 years ago

Just one other thing to keep in mind: If developer wants to preserve other query params or completely replace them. A better method name might be setQuery. That way you can leave it up to the developer to preserve or completely replace existing query params.

function addFooQuery({ input, services }) {
    const { param1, param2 } = input;
    services.router.setQuery({ param1, param2, foo: "foo value" });
}

function setBarQuery({ services }) {
    services.router.setQuery({ bar: "bar value" });
}
awei01 commented 8 years ago

Hi, I took some of @christianalfoni's suggestions and created a POC repo here: https://github.com/awei01/cerebral-module-router-POC