I am using route.navigate to go through pages, and I don't want to pass data in route params, because it is an object, or even array of items. But every time I try to set data in service and get automatically onInit when I get routed to another page I get undefined variable.
This shows, when I scan an item it automatically launches api to get that item data, and I want to pass that data to a page that is routed to
this.inv.getInvItems(this.itemKey).subscribe(data =>{
this.inv.setInvItem(data);
this.router.navigate(['/itemTake']); })
after this code it reroutes to item take
and setInvItem looks like this
setInvItem(data){
this.invItem = data;
}
but when I go to other page and trying to get that set data from same service it is undefined
console.log(this.inv.invItem);
any ideas? advices?
Pages are not child/parent type, it doesn't stay in same space it gets rerouted
App is being made in newest angular 7 cli
After 3 days of killing all my brain cells for not knowing this answer, now everything works fine, just for some reason it was cached or something, needed to launch on incognito and everything worked just fine
Related
I want to use *ngIf in my angular project. I use app.component.html to handle login page and as well as dashboard. So I want to hide dashboard before user login to the website. After user logged to the system I want to show the dashboard.
So I use *ngIf to handle this. I use following code to handle the case.
In my app.component.html I use following div to show when ever user is not log to the system.
<div class="login-page" *ngIf="!isLog()">
... go some code here...
</div>
And following div is use to show the dashboard after user is log to the system.
<div class="main-dashboard" *ngIf="isLog()">
... go some code here and router outlet as well ...
<router-outlet></router-outlet>
</div>
Finally in my app.component.ts file is use isLog() method to check whether user is logged or not.
isLog(){
// Use to back end api to check user log
var log : boolean = false;
// If User is Log
// Use back end api to handle this
log = true;
return log;
}
But the issue is when user try to log to the system for first time this code structure works fine for that case. But after user log to the system if user refresh the page for little time (0.5 ms > time) system shows the login page and suddenly shows the current page.
I think this is because every time user refresh the page website try to check user is log. During that time isLog() method return false so website shows login page for that time.
After isLog() return the valid value it means true. Then it shows the dashboard.
But I want to avoid this case. After user log to the system I don't want to show login page even for little time. Because user get confused.
How can avoid this case? Is there are any possible way to handle this type of issue?? OR recommended way???
If that's the case, try to store this info in sessionStorage which will persist the data for that tab and you wont have to wait for server response.
Also, as a side note, using *ngIf="isLog()" is not a good approach. You can try to put console.log in isLog() and you'll see it getting triggered periodically. That's because of change Detection cycle of angular which works on all the expressions assigned to template, and since *ngIf has function associated to it, that function (isLog()) is executed.
Its better if you can evaluate this value on ngOnInit and assign it some variable which will be used as a flag to check *ngIf condition
Of course it depends on your needs but the best practise is making the login page a seperate component and use Route Guards to protect the routes.
If having it in the same page and using ngIf is enough for your requirements which means you have a small application and it is not likely to expand, it is fine. The problem you experience is well explained by #Shashank Vivek in his answer.
I'm developing an IOS app that receives push notifications. Is it possible to open a specific page of my app when I receive it and click on the notification?
Yes it is possible and its part of a "thing" called Deep Linking.
Basically the idea is to architect your project where each view controller would be mapped with a URL-Scheme (yeah that string thing).
So that in applicationDidFinish you know which viewcontroller represents which URL-Scheme.
Now send the data in the push notification along wit the URL-Scheme of the viewController, you want the data to be shown. Write code in the method to parse and push that particular controller. This is the basic rough idea of how it would/should work, I might have missed out a few details, but here is a good article and tutorial on it, if you wanna go through.
Hope this helps
Our app does this, and to be quite honest, its a pain in the ass. But here is how we went about it:
Have a root view controller that handles all incoming notifications (usually via some kind of data source or manager class)
Create a model object to represent your notification and make sure this has a type property.
Create a typedef enum to store the different kinds of notifications your app can expect to receive.
The root view controller should implement a method with a switch statement that switches on the type of notification being handled.
The root view controller can then load up the correct view controller for your notification, so you pass the notification object to the view controller if you need to use any information held within it.
This is a basic overview, and you will need to adjust it to suit your navigation stack depending on how complex it is. It may be that you need to pass that notification object down a view levels in your view hierarchy (as we have to do).
Depending on how your application behaves, you may also need to consider how your application handles returning from the background to the foreground i.e. what state is it in when the app receives its notification and reset your navigation stack where appropriate so that your navigation stack reacts correctly.
You will receive control in the "didReceiveRemoteNotification" whenever user tap on the notification.
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let navigationController = storyboard.instantiateViewControllerWithIdentifier("DetailViewController") as! DetailViewController
self.window?.rootViewController?.presentViewController(navigationController, animated: true, completion: {})
}
Here you can also detect if the application is in active state or inactive and perform the presentation accordingly.
So get rootViewController and present the screen you need to show.
Also if you need to push the controller in already presented navigation stack, then you can fetch the navigation controller from window, then push the specific controller over it.
The decision to show the controller you need to present can be taken from the userInfo received.
This way you can open any specific controller you want.
I am using React with react-router and Reflux as my datastore, but I am unsure on how to best deal with persistence to allow page refresh.
My components connect to the store with Reflux.connect, but since the store fetches the data from a backend, it is not available yet when the Components first initialize and render.
When the user enters my app from the start, then all this data is loaded in order and available when it needs to be, but if further down a route you trigger a page refresh, react tries to render components that rely on data that is not there yet.
I solved this by constantly keeping a copy of data in LocalStorage and serving that from the Reflux store getInitialState(), so that all components get the data before they render.
I wonder if this is the proper way to do it. When for some reason the local storage data gets cleared or corrupted, the interface goes blank, because the components cannot access the correct data. Substructures and properties don't exist and trigger javascript errors. It seems like a messy and unreliable solution.
I am curious to know what patterns are used to solve this.
------ edit -----
To answer to the comment of WiredPrairie:
1) Why are you initializing components with data in getInitialState?
When my components use Reflux.connect, they don't have the data in their state yet on the first render as the store still needs to fetch its data. My views currently don't work gracefully with undefined data. By returning the locally stored cache from the Reflux store in getInitialState(), all connected components will get that data before their first render call.
2) What's causing a page refresh and why can't the data be loaded in the same manner as it was the first time?
It's mainly a workaround I had to build around livereload refreshing the page when I make edits (will look into using react-hotloader later but is not an options yet), but users can also just hit refresh when they are somewhere in my nested views and that would have the same effect. When they manually refresh, they are not entering the app at the start.
3) When components are wired to the change events of a store, why don't they update then?
They do update, but like I said they don't deal with empty data right now and on first render they will miss it waiting for the store to fetch things. I can make all my views work gracefully with empty data, but that would add a lot of boilerplate code.
From the replies so far, I get the feeling that what I'm doing with localStorage is the common way to do it. Cache stuff locally in localStorage or sessionStorage or something similar, and serve that data immediately after a refresh.
I should make my views a bit more robust by gracefully handing empty data on the odd occasion that localStorage doesn't work properly.
I've been caching each Store in sessionStorage when its emitChange() fires, and initializing the store from sessionStorage if cached data exists, or null values otherwise. This seems to work provided that the views can handle null values, which is probably a good idea anyway (it sounds like this is your main problem).
I'd suggest making your views handle the case of no data gracefully, initialize everything with null values if the cache isn't available, and then call the backend to update the null values with an Action whenever the data returns.
I haven't tried Reflux, but in regular Flux it would look like this (maybe you can apply the same principle):
var _data;
if (sessionStorage.PostStore)
_data = JSON.parse(sessionStorage.PostStore);
else {
_data = {
posts: null
};
BackendAPI.getPosts(function(err, posts) {
if (posts) {
PostActions.setPosts(posts);
}
});
}
...
AppDispatcher.register(function(payload) {
var action = payload.action;
switch (action.actionType) {
...
case Constants.SET_POSTS:
_data.posts= action.data.posts;
break;
default:
return true
}
// Update cache because state changed
sessionStorage.PostStore = JSON.stringify(_data);
PostStore.emitChange();
return true;
});
I've got a phonegap-wrapped sencha touch (v1.1.1) app that has a few stores, and a list.
The problem occurs after you're logged in as "User1", and then log out and log back in as "User2". The list won't refresh with the new account data fetched by the store proxy.
I'm currently attempting to call .refresh() on the List itself, which according to the docs will also cause the store to refresh its data (although, I'm manually doing that before hand anyway)
var sL = Ext.getCmp('AccountsList');
sL.refresh();
sL.scroller.scrollTo({x:0,y:0});
We've also tried to .sync() the stores with no results.
Ext.getStore('AccountsTransfersTo').sync();
Ext.getStore('AccountsTransfersFrom').sync();
Ext.getStore('AccountsStore').sync();
Any idea what the problem is, or has anyone run into something similar?
refresh won't reload the store, it just grabs whatever is in the store and re-renders the view.
sync is for updating the store when you've got local changes and you're posting them to the server.
You need to call the load method on the store.
It sounds like a caching problem. or a state problem.
a link:
http://html5wood.com/sencha-touch-difference-between-ext-get-and-ext-getcmp/
from the page:
Sencha Touch: Difference between Ext.get() and Ext.getCmp()
Important: It returns the same element object due to simple caching on retrieving again. It means it returns wrong element on second time. Ext.fly() can be used for avoiding this problem.
hope it helps
mike.
You may Load the store each time
var sL = Ext.getStore('AccountsTransfersTo')
sL.load();
sL.scroller.scrollTo({x:0,y:0});
or you may try to clear data form store and reload it again
var sL = Ext.getStore('AccountsTransfersTo')
sL.removeAll();
sL.load();
sL.scroller.scrollTo({x:0,y:0});
I have a simple app written in meteor here: https://gist.github.com/drew-gross/6202629 that is having problems. When the Template.tab.ordered_drinks function is called, no Tabs are found (Tabs.find({}).fetch() returns an empty array) but only most of the time. Sometimes the Tabs are there. I have checked that they exist in the database.
To reproduce:
1) Run the app. (requires meteor-router)
2) Create a tab on the console: Tabs.insert({owner:"foo"})
3) Try to view the page for the tab: localhost:3000/tabs/:id
The page will work or not work, seemingly at random. To confirm, you can set a breakpoint on line 9 or 19 of the .js and do Tabs.find({}).fetch() and you will sometimes see and sometimes not see the tab.
This kinda seems like a bug in Meteor but I thought I would check first to see if I might be doing something wrong.
Browser: Chrome 28
Meteor version: Release 0.6.4.1
Node version: v0.10.15
It looks like the issue might arise if the subscriptions haven't yet got their data.
In meteor the html/js is sent down to the client, it then renders the page. At the same time the client connects to the server via websockets/long polling to retrieve the mongo database.
So sometimes you can render html without yet having anything in your database.
You just need to be careful that you use reactivity to handle when the data arrives and not presume its already there, like here:
Template.tab.ordered_drinks = function () {
return Tabs.findOne(Session.get('tabId')).ordered_drinks;
};
if Tabs.findOne(Session.get('tabId')) is null because there isn't any data on the client (yet) then .ordered_drinks wont exist and you would get an error on the chrome console & sometimes see/sometimes not see the tab, depending on whether the database has loaded yet or not.
Try altering the line below to allow Tabs.findOne(Session.get('tabId')) to be null without throwing an error.
Template.tab.ordered_drinks = function () {
var tab = Tabs.findOne(Session.get('tabId'));
return tab && tab.ordered_drinks;
};
So at this point it is loading. As soon as the data arrives it'll reactively re-render this portion with the tabs.