I have an Angular application with uiRouter and some data that I want to display using Angular-Chart.js.
I have different filters that can be applied to this data. I also want to have a URL that represents the state with all applied filters, i.e. /:groupId/:dateStart/:dateEnd
Right now I have a state with parameters, and two views (controller+template) - one for displaying data and one for displaying filters. In the filterController, I have a function that is called when the filter is changed, and that function simply calls $state.go("Controller", newFilterParams);
That approach works, however, that fully reloads the controller for the data, and I want to prevent it and animate the data change. But I also want to preserve the URL representation.
Is that possible? What would be the best practice to implement data filtering in Angular and uiRouter?
Related
I have a project which contains (among other things) a list view of events, and then of course a unique page showing these events individually, you can easily understand there are two distinct path : /events/ and /events/:id
I added some filtering on events, and of course when I filter the list, and then click a specific event to see it, and then go back to the events list, it of course, forget about my filter.
Should I use Contexts or is there a specific way I didnt hear about ?
I also thought about having different path for all the filters (ie : /events/filter_type_1 etc etc with filter_type_1 being something human readable.)
What would be the more logical way ?
Yes and no there 3 ways to solve this:
Store state in higher component
instead of storing state in your overviewView component. store it in the component above that does the routing. this way it wont get lost on navigation. (i dont like this approach).
Persist state
You could persist the state to the localStorage and read this state when your component mounts. this way when you come back your state will have persisted.
localStorage.getItem("overviewCompnent_filter");
localStorage.setItem("overviewCompnent_filter",yourData);
Externalize state
There are state libraries that help you put top level application state outside of react components like: mobx (my favorite) and redux. These libraries use the context api underneath to deliver the right state/values to your component and you can let them make it inject them as props in your component (so it's like the first option but a cleaner solution).
This way you can keep all your top level state together and not have to give it all the way down your component tree.
I am building a test application using reactjs and refluxjs where I show a list of images from an API with pagination.
Currently I have one PicturesStore and two actions: RefreshAction and PageChangeAction.
The filters for filtering the images that I fetch from the server are in the PicturesStore.
The RefreshAction is emitted to fetch new images from the server based on the filters that live in PicturesStore.
The PageChangeAction is emitted to refresh the filter (by changing the page number) and then emit the RefreshAction to refresh the pictures.
I am a bit lost on how to proceed here. I can think of two approaches to change the current page number and fetch the images from the server based on this page number and the filters that live inside PicturesStore, but I don't know which one could be the best or if there's a better one.
1st approach: emit the PageChangeAction in the react component and update the page number inside the PicturesStore. Once updated, emit the RefreshAction from the PicturesStore (call an action inside a store).
2nd approach: emit the PageChangeAction, update the page number inside the PicturesStore, use CathegoryChangeAction.changePage.listen method to trigger the RefreshAction (emitting an action inside of another action), but the problem is that inside RefreshAction I need to access the filters that live inside PicturesStore (accessing a store inside an action).
Please let me know if I've been clear enough.
My current reactjs/flux implementation is to have components call actions, and actions call the web api which then funnels back to the store.
I have a set of checkboxes where the state of the checkboxes are managed in a store, but every time I update the checkboxes, I would like to make a query to the server with the state of the store. What I am forced to do now is call an action to update checkboxes store when the checkboxes are clicked, in the checkboxes store, set a variable to "queryServer", then in the checkboxes component, check the "queryServer" and make another action to query the server.
It seems simpler if both components and stores can make action calls, that way, when I update the checkboxes store, I can initiate the action to query the server directly without setting a silly "queryServer" variable and having the component check that.
Though it does seem to make things simpler, it seems to go agains the essence of the flux architecture where all actions are initiated from the view.
My approach would be to fetch the state of the store into the view and pass it to an action from there. This would allow your store to stay as dumb as possible, simply receiving data as it comes into the application.
In more specific terms, your store would have a getData function that returns the raw data stored. In your component the click handler for your checkboxes would include code looking something like this:
var data = MyStore.getData();
MyActions.queryServer(data);
Your action would then make the API call (since it's probably the safest place to do anything asynchronous) and pass the new data to your store via the dispatcher.
I'm trying to build a reusable component that I can use to load ads via Doubleclick (DFP) asynchronously. The problem I'm running into is there are several dependencies before an ad can actually load, and I'm not sure the best way to handle the communication and sequence. Because the ad components render anywhere on the page and don't render as part of a parent, I'm not sure how to handle it since I can't embed ads inside of a parent to communicate.
In this article:
http://facebook.github.io/react/blog/2013/11/05/thinking-in-react.html#step-4-identify-where-your-state-should-live
There is this potential solution, but after some searching I wasn't able to find an example that doesn't tie the rendering together.
"If you can't find a component where it makes sense to own the state, create a new component simply for holding the state and add it somewhere in the hierarchy above the common owner component."
Here are the details/steps:
1). I first need to load the JS http://www.googletagservices.com/tag/js/gpt.js
This creates a global googletag object.
2). I need to set global targeting (i.e. site name, content type, etc) that will apply to all ad tags (configurable).
Example
googletag.pubads().setTargeting('site', window.location.hostname);
3). I need to define the ad slots and targeting for individual ad slots that React rendered.
googletag.defineSlot('/12345/zone', [[300, 250], [300, 600]], 'div-gpt-ad-300x250-0').addService(googletag.pubads()).setTargeting('pos', 'sidebar_300_1');
4). I need to specify settings globally
googletag.pubads().collapseEmptyDivs();
googletag.pubads().enableSingleRequest();
googletag.enableServices();
5). I need to render the ad slots (with the option to render individually or globally)
googletag.cmd.push(function() {
googletag.display(divIdAttribute);
});
or just
googletag.display();
I Initially created two components: a DFPManager that loads the required Javascript once, and then a DFPAd that actually handles the individual ads. I couldn't figure out the communication.
I also need to be able to reload individual ads based on external events (i.e. ajax page change) or create new ads as a user scrolls into infinite scroll content.
Is the best solution to manage my own events system where I put listeners in my components to depend on external events, or is there a better way to manage this? In that case I wouldn't necessarily need a DFPManager since no rendering takes place there and I could trigger an event when ready. This is a similar problem for analytics tracking where I need to track pageviews based on external events, but only after first loading an initial javascript (i.e. Google Analytics tracking js).
<div id="300-250-ad"></div>
<script type="text/jsx">
/** #jsx React.DOM */
React.renderComponent(
<DFPAd size={[[300, 250], [300, 600]]} targeting={[["pos", "sidebar_300_1"]]} />,
document.getElementById('300-250-ad')
);
</script>
I may be overthinking this. Appreciate any suggestions.
Turning DFPManager into just an object which fires change events sounds like a good plan. It wouldn't be a React component itself any more. The individual ad components could accept the store object as a prop, then subscribe to the change events in componentDidMount, and unsubscribe in componentWillUnmount. The onChange handler could call setState with the current data from the store, which will trigger a re-render.
The store could be implemented like the store in the Flux TodoMVC example, which uses an EventEmitter base class. If there is no interactivity, using a full dispatcher is probably overkill, since there won't be any user actions by the sounds of it.
In my app, i have no.of pages. each pages have a separate view for them. But in the header part i need to show the user name on all views rendering.. what would be the best practice for that..
i came across with some of options saying..
1. render the header view even before the router starts
2. use the routers '*' - notation to call the header view always.
3. keep the header view as a sub view of all page views - and keep call header view on all page view..
what would be the correct way...please any one suggest me the best way.
Have a layout view that contains the header and gets rendered only once. Then just render the interior portion of the document as you navigate. Changing the URL and triggering a new route does not always imply the entire DOM needs to re-render. Keep your DOM changes as small as possible. Also study the idea of nested views like you get with Backbone.Marionette for another approach.