I'm using FirebaseUI for Web — Auth widget to simplify the auth workflow, and I'm stuck with a problem. Everything works OK the first time. But, after I sign in, the widget contents clears away, and the 'Sign in with ...' buttons never come back. Trying to recreate the widget brings up the error "UI Widget is already initialized on the page. Only one widget instance can be initialized per page."
This means that users need to refresh the page to get the sign-in buttons back. Is there a more elegant way?
Are you rendering the widget in a single page application? If so, this currently won't work. You will have to render the sign in widget in a popup whenever you want the user to sign in.
As bojeil stated in the first answer (May 2016), there was really a problem using it in single page applications workflows. But in more recent versions of firebase-ui you can actually reset the widget so you won't need to initialize it again.
All you need to do is to keep the widgets instance reference in a variable. Then, when you want to render it again you use the same reference, reset it and then restart it.
var ui;
if (ui) {
ui.reset();
} else {
ui = new firebaseui.auth.AuthUI(firebase.auth());
}
ui.start('#firebaseui-auth-container', uiConfig);
Related
I am developing a Xamarin.Forms app with Prism in which I'd like to incorporate an onboarding page (more specific a top user benefits page, following the Material Design guidelines).
The app itself is structured around a NavigationPage to which I navigate with
NavigationService.NavigateAsync("/NavigationRootPage/MainPage")
in my App(). On the first start I'd like to show the onboarding page instead and I am having quite some issues getting it right.
My first approach was to navigate to MainPage with
_navigationService.NavigateAsync("/NavigationRootPage/MainPage")
from my viewmodel, when the user clicks the Get Started! button. This kind of worked by is also kind of ugly, since this absolute navigation will destroy the oboarding page immediately and not animate the transition. Furthermore at the moment the oboarding page is destroyed, the MainPage will be built, which will take a small, but noticeable, amount of time. In effect the user will notice the MainPage being built up, which does not look smooth at all.
My second approach was to navigate in a relative fashion from my viewmodel.
_navigationService.NavigateAsync("NavigationRootPage/MainPage")
This works way smoother, with the transition animation and after the animation is done, the MainPage is already ready to go. But again there is a major drawback. You can navigate back to the onbaording page, which we dont't want neither. And - to my knowledge - there is no (clean) way to remove the page from the navigation stack, too. I tried calling PageUtility.DestroyPage on my onboarding page, but this only worsened things, since it seemed to keep the page, but destroy the viewmodel, resulting in my onboarding page being shown without data when pushing the back button.
My third approach did not work at all, although it seemed promising to me. In my App() I pushed my navigation page with the main page then then my onboarding page modal
NavigationService.NavigateAsync("/NavigationRootPage/MainPage");
NavigationService.NavigateAsync("OnboardingPage", useModalNavigation: true);
and then in my viewmodel
_navigationService.GoBackAsync(useModalNavigation: true)
but this approach
showed the header of the NavigationPage although the onbaording page was supposed to be shown as a modal
refused to GoBackAsync - when calling this method, nothing happens
waiting for the first call to NavigateAsync did not change anything either.
Some other things I've tried
Implemented INavigationOptions in my viewmodel with ClearNavigationStackOnNavigation being true
Tried setting Application.MainPage after my NavigationPage was shown, but to no avail
I would have believed that this was king of a common requirement when programming an app. Is there something I've missed? Or will I have to live with one of those drawbacks?
I think you are overthinking this. If you want to show your Onborading page first then just navigate to it first.
`NavigateAsync("NavigationPage/OnboardingPage");
Or if you want to have the MainPage in the stack, then start the app with a deeplink
`NavigateAsync("NavigationPage/MainPage/OnboardingPage");
If you don't want to show the navigation header, just hide it for the onboarding page.
Don't use an absolute navigation unless you want to completely reset the navigation stack (equivalent to MainPage = new MainPage()).
I have found a solution, which is not the most beautiful one (it is actually quite ugly) but working.
In my MainPages viewmodel I implemented INavigatingAware and navigated to my OnboardingPage modally
public async void OnNavigatingTo(NavigationParameters parameters)
{
await _navigationService.NavigateAsync("LandingPage", useModalNavigation: true);
}
However, removing the moal page with
this._navigationService.GoBackAsync(useModalNavigation: true);
does not work as expected. The modal is not removed (although it should work this way from looking at the code, but I did not manage to debug with Re# generated PDBs). Hence I had to go the ugly (non-MVVM) way and create an event handler for Button.Click and remove the modal manually
private void Button_OnClicked(object sender, EventArgs e)
{
this.Navigation.PopModalAsync();
}
This will return to my MainPage smoothly with an animation and my MainPageis already up and running without being built up while already visible.
Still, I'd appreciate an answer on how to do it the Prism way.
In PrismForms we got the problem, that the NavigationStack is empty after navigating to a new page. That means after using the hardware back-button on the SecondPage, the app is closed. Although the back-arrow in the header on Android isnt shown. If looking closely you can see the back-arrow for a short moment after the page is switched. I guess thats before the NavigationStack gets cleared.
To the first page we navigate with the following command in OnInitialized() in our App.xaml.cs which derives from PrismApplication.
NavigationService.NavigateAsync("NavigationPage/StartPage");
(If only Navigating to „StartPage“ here, the Stack doesnt get cleared.)
That has do to with PageNavigationService.ProcessNavigationForNavigationPage(...) calling
bool clearNavStack = GetClearNavigationPageNavigationStack(currentPage); and PageNavigationService.ProcessNavigationForContentPage(...) not.
From the StartPage to the next we navigate with NavigateAsync("SecondPage")“. Here the described behaviour appears.
For navigation we use a class which wraps the Prism NavigationService. We hold him as a property and get him via Unity in our constructor:
this.PrismNavigation = prismNavigation ?? throw new ArgumentNullException(nameof(prismNavigation));
The methods „NavigateAsync“ and „GoBackAsync“, etc. we just pass through.
This way we want to seperate our ViewModel-Project from references to XamarinForms to later be able to use the same ViewModels for for example a WPF-GUI.
Why is the stack beeing cleared by our own NavigationService? If we register the original Prism NavigationService in App.xaml.cs instead, navigating back works as expected again. We found the point in the framework and could avoid the clearing with a drity hack, but that’s against the navigation-logic implemented in PrismForms, but we don’t understand how to do it the correct way.
Every help appreciated!
We edited a few things to get it working after finding some interesting information by Brian Lagunas in the forlast-post here:
https://github.com/PrismLibrary/Prism/issues/591
Although the topic was about something else, it led to improvements for overwriting the Navigation Service.
Remember that in your viewModels the Navigation Service must be named "navigationService" by convention. Also we switched from just holding the Prism Navigation Service as a parameter to deriving from it as suggested in the link above.
public class MyNavigationService : UnityPageNavigationService
So I would like to be able to have a print button for entries in our database so users can print an entry via a print friendly "form".
My thought was to create a separate page, add labels and have those labels pull the relevant information.
I know I can add the open widget information via this code:
app.datasources.ModelName.selectKey(widget.datasource.item._key);
app.showPage(app.pages.TestPrint);
But I'm running into a few problems:
I can't get the page to open in a new window. Is this possible?
window.open(app.pages.TestPrint);
Just gives me a blank page. Does the browser lose the widget source once the new window opens?
I can't get the print option (either onClick or onDataLoad) to print JUST the image (or widget). I run
window.print();
And it includes headers + scroll bars. Do I need to be running a client side script instead?
Any help would be appreciated. Thank you!
To get exactly what you'd want you'd have to do a lot of work.
Here is my suggested, simpler answer:
Don't open up a new tab. If you use showPage like you mention, and provide a "back" button on the page to go back to where you were, you'll get pretty much everything you need. If you don't want the back to show up when you print, then you can setVisibility(false) on the button before you print, then print, then setVisibility(true).
I'll give a quick summary of how you could do this with a new tab, but it's pretty involved so I can't go into details without trying it myself. The basic idea, is you want to open the page with a full URL, just like a user was navigating to it.
You can use #TestPrint to indicate which page you want to load. You also need the URL of your application, which as far as I can remember is only available in a server-side script using the Apps Script method: ScriptApp.getService().getUrl(). On top of this, you'll probably need to pass in the key so that your page knows what data to load.
So given this, you need to assemble a url by calling a server script, then appending the key property to it. In the end you want a url something like:
https://www.script.google.com/yourappaddress#TestPage?key=keyOfYourModel.
Then on TestPage you need to read the key, and load data for that key. (You can read the key using google.script.url).
Alternatively, I think there are some tricks you can play by opening a blank window and then writing directly to its DOM, but I've never tried that, and since Apps Script runs inside an iframe I'm not sure if it's possible. If I get a chance I'll play with it and update this answer, but for your own reference you could look here: create html page and print to new tab in javascript
I'm imagining something like that, except that your page an write it's html content. Something like:
var winPrint = window.open('', '_blank', 'left=0,top=0,width=800,height=600,toolbar=0,scrollbars=0,status=0');
winPrint.document.write(app.pages.TestPage.getElement().innerHTML);
winPrint.document.close();
winPrint.focus();
winPrint.print();
winPrint.close();
Hope one of those three options helps :)
So here is what I ended up doing. It isn't elegant, but it works.
I added a Print Button to a Page Fragment that pops up when a user edits a database entry.
Database Edit Button code:
app.datasources.ModelName.selectKey(widget.datasource.item._key);
app.showDialog(app.pageFragments.FragmentName);
That Print Button goes to a different (full) Page and closes the Fragment.
Print Button Code:
app.datasources.ModelName.selectKey(widget.datasource.item._key);
app.showPage(app.pages.ModelName_Print);
app.closeDialog();
I made sure to make the new Print Page was small enough so that Chrome fits it properly into a 8.5 x 11" page (728x975).
I then created a Panel that fills the page and populated the page with Labels
#datasource.item.FieldName
I then put the following into the onDataLoad for the Panel
window.print();
So now when the user presses the Print Button in the Fragment they are taken to this new page and after the data loads they automatically get a print dialog.
The only downside is that after printing the user has to use a back button I added to return to the database page.
1.
As far as I know, you cannot combine window.open with app.pages.*, because
window.open would require url parameter at least, while app.pages.* is essentially an internal routing mechanism provided by App Maker, and it returns page object back, suitable for for switching between pages, or opening dialogs.
2.
You would probably need to style your page first, so like it includes things you would like to have printed out. To do so please use #media print
ex: We have a button on the page and would like to hide it from print page
#media print {
.app-NewPage-Button1 {
display : none;
}
}
Hope it helps.
1. Here is how it is done, in a pop up window, without messing up the current page (client script):
function print(widget, title){
var content=widget.getElement().innerHTML;
var win = window.open('', 'printWindow', 'height=600,width=800');
win.document.write('<head><title>'+title+'/title></head>');
win.document.write('<body>'+content+'</body>');
win.document.close();
win.focus();
win.print();
win.close();
}
and the onclick handler for the button is:
print(widget.root.descendants.PageFragment1, 'test');
In this example, PageFragment1 is a page fragment on the current page, hidden by adding a style with namehidden with definition .hidden{display:none;} (this is different than visible which in App Maker seems to remove the item from the DOM). Works perfectly...
2. You cannot open pages from the app in another tab. In principle something like this would do it:
var w=window.parent.parent;
w.open(w.location.protocol+'//'+w.location.host+w.location.pathname+'#PrintPage', '_blank');
But since the app is running in frame nested two deep from the launching page, and with a different origin, you will not be able to access the url that you need (the above code results in a cross origin frame access error). So you would have to hard code the URL, which changes at deployment, so it gets ugly very fast. Not that you want to anyway, the load time of an app should discourage you from wanting to do that anyway.
i am using custom url scheme in my flex iOS app and it’s working fine when i start my app from a web link..but the issue is when i start my app from start menu in iPad and move to webpage in safari.In page i click a button that redirects it to my app, at that time app call “preinitialize” method more than once..it wary every time, some time it’s 2,3,4 and different one each time..i don't know why it’s behaving like this..can i know the reason please its urgent..
thanks…any help will be appreciated.
Create a flag initialized and set it to true when preinitialize is called. All other calls to this method can be filtered out. Simple example:
private var initialized:Boolean = false;
public function preinitialize():void
{
if (initialized) return;
initialized = true;
}
Next step would be finding the real cause of the multiple calls, but for that we would need to see some code of your app.
Sometimes when opening a form or when clicking on an object on the form, the form goes inactive or opens in the background. Is there a way to prevent this from occurring programatically?
I have seen this from time to time, but I don't have any documented solution.
You could try to clear the users AUC cache and see if that helps.
I have found the answer to this question. It is related to a 3rd party addition that we have installed (IEM). I had to remove some code that they have that sets forms as modal (which ends up putting them in the background because of the base timeout function in AX because the code to make the form modal takes too long to execute). I had to make a change to Classes/SysSetupFormRun: Below is the code and where it was changed
public void activate(boolean _active)
{
;
// if (_active)
// PUL_Modal::construct().hookModal(this);
super(_active);
/*
if (_active)
PUL_Modal::construct().checkModal(this);
*/
}
This returns the activate method to its previous state and prevents forms from going modal.