Creating Angular 2 component before the router does - angular2-routing

According to the documentation,
When the browser's location URL changes to match the path segment /crisis-center, then the router activates an instance of the CrisisListComponent and displays its view.
Is there a way to " pre-activate " an instance of a component before navigating to the corresponding route, so that the router can then display its view immediately without having to create an instance itself?
Thank you very much.

Not sure if this helps, But you can pre-fetch component data, before Routing completes.
So when routing happens data can be fetched in the resolver, and component gets loaded only after that. you may write some event Hooks on router to display loader while routing is not complete.

Related

How to listen to page url change in React?

I have a react component that is rendered in two different pages and I want it to have different css for each page. So I passed it a prop to switch between the css classes, but, because there is no page refresh between the 2 pages, my component doesn't change the css class, only if I manually refresh the page, my component sees the prop I passed and changes the css class.
Can anyone tell me how can I make the component rerender on page change ? even if there is no page refresh?
I tried, until now, to change the state of the component with componentDidUpdate, but it ends up rerendering on a infinite loop, and the page doesn't load anymore.
Is there any other way to do this ?
I think you can solve the problem using history. This will help you to track the URL changes.
if you're using a functional component you can use useParams
the second solution that comes to my mind is to use the param as the key of the component, that will force the re-render.
I imagine you are using react router dom, if so I think getting the location by doing useLocation() would achieve the desired result as when the url changes this hook would cause a re-render
const location = useLocation()

How Do I Measure a Single Page Website That Uses URL Fragments with Tealium/GA?

I was asked to capture the analytics on a website. The website is made up of 5 web pages, but I now realize that the domain is the same and the only thing that changes is the URL fragment, i.e. www.domain.com#a, www.domain.com#b. The only info that comes through to GA is the domain and it does not include the URL fragments. The tracking code I'm using is Tealium and the data is being sent back to Google Analytics. How can I set this up so that i can see the entire URL in GA including the URL fragments?
So, from Tealium's perspective we need to trigger a view event when a new fragment is loaded (if I am understanding this correctly).
If we assume that the fragment change occurs on a link click then we need to trigger the view event when the link click occurs.
From the GA perspective, we need to trigger a view that captures the new information. For a view this is likely to be location, path and title.
Therefore, we need Tealium to construct the new data points and then pass them in a view event to GA.
The simplest way to do this in Tealium (all things being equal) is via a jQuery onHandler Extension
The jQuery extension requires the following information:
jQuery selector (or selectors) to pay attention to
"Trigger On" event type (this will be Click in this example)
Tracking event type to run (View event in this case)
Variable & values to set
Tealium jQuery onHandler extension config
note it's always a good idea to set a condition on your jQuery extensions so that they only run when needed instead of all the time and everywhere
In this extension, I have set the following:
jQuery Selector: '#MyID_1, #MyID_2, #MyID_3' -- yes you can pass a list of selectors or nearly any other valid jQuery selector statement
Trigger On: 'click'
Tracking Event: 'view'
3 Variables:
a. 'page_name' : $(this).text(); //get the link text
b. 'my_url' : utag.data['dom.url']+$(this).attr('href') //building the full URL including the fragment
//utag.data['dom.url'] is a variable/datapoint that Tealium automatically generates
c. my_path : utag.data['dom.pathname']+$(this).attr('href'); //building the path
//utag.data['dom.pathname'] is a variable/datapoint that Tealium automatically generates
NOTE: make sure to set the type for each these to "JS Code" otherwise your JavaScript will be quoted out as a string.
Why these three variables? As I understand GA, these are the values it would expect for a new page view -- location/URL, path, and Title so we are constructing those values in the extension to pass them to GA on the view event.
Now, we just need to map these new variables to GA.
my_path gets mapped to page in the GA mapping toolbox
page_name gets mapped to title
location isn't a default option in the mapping toolbox so we need to add a custom destination variable called location and map my_url to it.
custom variable mapping for GA
That's how you do it from within Tealium and minimal coding. If for some reason you don't want to / can't do it inside of Tealium, this provides us with a very nice template for a custom function to add to our codebase:
`$(document.body).on('click', '#altID', function(){
utag.view({
"page_name": $(this).text(),
"my_url": utag.data['dom.url'] + $(this).attr('href'),
"my_path": utag.data['dom.pathname'] + $(this).attr('href')
})
})`
See both in action over here at CodePen.

Dispatching several actions in sequence for single reducer doesn't reflect changes in state for connected component

When dispatching several different actions for one reducer, only the last one triggers component update. It might be better to show then explain.
Some notes on provided example:
App component reflects a history of updates of it's prop redirectPath. When it comes as null then no redirect string adds to history.
There is a reducer which returns just a plain string or null depending on action.
By pressing a button Do redirect I expect both actions (SET_REDIRECT and CLEAR_REDIRECT) provide changed state to AppContainer component. But only the latest one (CLEAR_REDIRECT) triggers render method with null value.
If we add slight delay between dispatching these actions, then both of them trigger component's render. You can check it by pressing Do redirect with delay button.
I expect both changes (provided by SET_REDIRECT and CLEAR_REDIRECT actions) in state should trigger component update without using setTimeout when dispatching actions.
I also tried to move dispatching of CLEAR_REDIRECT from middleware, after it gets SET_REDIRECT, but the same result.
Can I somehow reach expected behaviour?
Initially I posted the issues to redux repo, because I thought it's an issue in redux, but #jimbolla explained me that it's mostly by design of react.
Here is the reference to the original issues and comments from redux team member https://github.com/reactjs/redux/issues/2532.
Don't ever rely on performing state updates in render(). The only code that should be executed in render() is the code required to construct the view.
You could use componentWillReceiveProps to track when your component receives new properties.
You should listen for the appropriate property and perform your redirect when received. You should then listened for a property that indicates the redirection was successful and then you can dispatch an action to clear the redirect state if required which will trigger another component update.

Angular2 Change Detection with Zones

I am wondering if all asynchronous events and callbacks can be traced back to a specific source component by wrapping all component logic (including logic of non-component directives inside component) in a zone, then only that source component needs to be checked for changes along with any child components with changed inputs from the source component, assuming all changes are following the uni-directional flow.
Is this understanding sound?
Is this change detection strategy available in Angular2?
Why is Angular2 detecting changes on all the components after any asynchronous (XHR) event?
One whole Angular application runs in a single zone. Angular uses the zone to patch async APIs and uses notifications from these patched APIs to run change detection every time some async event happened.
The uni-directional flow is for [prop]="value" bindings that works only from parent to child.
Angular runs change detection from root to leafs.
If ChangeDetectionStrategy.OnPush is configured for a component, change detection skips these components (and their descendants) until some binding (inputs) have changed.
There are other strategies to optimize CD.
For example observables and promises, that actively notify about changes and don't need change detection.
Immutable objects which are guaranteed to not change their propery values.
Update
Angular doesn't know what values an event handler has changed. Properties of a component, of a global service, of object references that were passed around, .... It just assumes that when an event handler was called that probably something has changed and then runs a complete change detection cycle to propagate all bindings from parent to child.
Child do parent bindings are events anyway and therefore aren't updated during change detection.
... by wrapping all component logic (including logic of non-component directives inside component) in a zone, then only that source component needs to be checked for changes along with any child components with changed inputs from the source component, assuming all changes are following the uni-directional flow. Is this understanding sound?
When an template-bound event fires – e.g., (click)="doSomething()" – the doSomething() method is free to alter any component or application data. Template statements, such as our doSomething() event handler, are not bound by the unidirectional flow rule, as per the Angular docs:
Responding to events is the other side of Angular's "unidirectional data flow". We're free to change anything, anywhere, during this turn of the event loop.
This is why, by default, Angular's change detection has to check every template binding in every component after an event fires. (Well, after an event within the Angular zone fires.) Angular doesn't know what might have changed... it has to discover what has changed.
The unidirectional flow rule applies to template expressions such as {{some expression}} or [childInputProperty]="parent expression" or if you implement an input property setter method: #Input() set childInputProperty(variableName:type) { ... }.
Is this change detection strategy available in Angular2?
No, because it would severely limit what an event handler could do. Dirty-checking every template binding may not be the most efficient way to detect changes, but it makes it much easier for us to write our event handlers (i.e., to write our applications).
Why is Angular2 detecting changes on all the components after any asynchronous (XHR) event?
Angular doesn't want to limit what we can do in our event handlers. An event handler bound in ComponentA's template can change data that is local to ComponentA, but it can also change data that is in a service (and hence it can change data that is visible to other components), and it can change data in other components, e.g., by calling public APIs/methods on other components.

How to implement a button with a backend action in OpenWRT LUCI without UCI side effects

I am trying to to implement a button in LuCI which, when clicked , runs a shell script in the backend. This is the model code for this:
field_var_36 = section_var_7:option(Button,"buttonkk36",translate("ButtonKK"))
field_var_36.inputstyle = "apply"
field_var_36.rmempty = true
function field_var_36.write(self, section)
luci.sys.call('echo "ABCDEFG123" >/dev/null')
end
Though this is working it has some unwanted side-effects. All the unsaved modifications in the page are getting saved and I get a "n unsaved changes" notifications at the top. My guess is the the button if of type "submit" and all the fields inside the html "form" are getting "sumbitted". I dont want this to happen. The button needs to be standalone. Can this be done?
One other option I tried was using a template with button implemented in html. But I dont know how to connect this to the backend script. Is there a javascript API function in LuCI which takes the script as argument?
Thanks in advance for any help.
I did that using a view template.
You must set up an "entry(...)" in an "index()" function in the "controller/" directory.
The entry associates a path (last part of the LuCI URL's) with either a template view, cbi or LUA function, which is just what you want.
Pay attention that when you change by hand a controller file on the target openwrt device, you must delete /tmp/luci-indexcache so that the LuCI dispatcher does not use the older version.
Then in the template you can use "luci.dispatcher.build_url()" to create the URL that will make the controller call the function, and you put this as the target URL for your button (through either or or onClick="document.location=..."> and so on)

Resources