Calling of function of one page from another page in blackberry cascades using qml - blackberry

In my application I have a main.qml which has a navigation pane that goes to homepage.qml and from there to profilepage.qml. When I come back from profilepage to homepage I need to trigger a function in home page. I noticed that whenever I pop back I get a call onPopTransitionEnded in the main page. Since homepage is pushed from main.qml there is no navigation pane on homepage and I cant access onPopTransitionEnded on homepage. Below are the sample structures of my 3 qml views.
main.qml
NavigationPane {
id: nav
peekEnabled: false
onPopTransitionEnded: {
console.log("POP PAGE from main");
if(page.objectName=="newProfilePage")
{
//I tried to access the function using the homepage id but didnt work
menuScreenPage.reloadView(); // This doesnt work, shows error unknown symbol menuScreenPage
}
page.destroy();
}
Page {
id: mainPage
Container {
//some code
}
onCreationCompleted: {
//Some code and then push to homepage
nav.push(homePageDefenition.createObject());
}
}
}
homepage.qml
Page {
id: menuScreenPage
objectName: "menuScreenPage"
function reloadView() //This is the function that is needed to be called on page pop from profile page
{
//some code
}
Container {
//some code
Button { //a button to push to profile page
id:pushButton
horizontalAlignment: HorizontalAlignment.Right
verticalAlignment: VerticalAlignment.Bottom
onClicked: {
console.log("I was clicked!")
nav.push(profilePageDefinition.createObject());
}
}
}
}
profilepage.qml
Page {
id: newProfilePage
objectName: "newProfilePage"
Container {
//some code
Button { //a button to pop to home page
id:popButton
horizontalAlignment: HorizontalAlignment.Right
verticalAlignment: VerticalAlignment.Bottom
onClicked: {
console.log("I was clicked!")
nav.pop();
}
}
}
}
So is there a way that I can access the function of homepage.qml from main.qml? Or is there any other function like onPopTransitionEnded which I can access on homepage.qml itself when I pop from profilepage? Please advice.

Seems that you created unnamed object with this line:
homePageDefenition.createObject()
If you want to access it later, you should save it in some property, for ex.
property var myHomePage: null
...
myHomePage = homePageDefenition.createObject()
nav.push(myHomePage )
...
myHomePage.reloadView();
Keep in mind that "menuScreenPage" is local name (id), it works only inside homepage.qml and nobody can access it beyond that file.
UPD
You can even use such code:
page.reloadView(); // Use local variable "page" instead of internal id "menuScreenPage"

Related

Jetpack Compose navigation: login screen and different screen with bottom navigation

My goal is to to have a LoginScreen from which I can navigate to an InternalScreen. The InternalScreen should have/be a bottom navigation bar that can navigate to multiple other screens/routes in the internal space.
This is what I imagined my NavGraph was supposed to look like:
- LoginScreen
- internal space
- InternalScreen with BottomNavigation
- some fragment
- some other fragment
My idea was to create a Scaffold with a BottomNavigationBar in the InternalScreen composable but I do not no where to put it in my NavGraph since said NavGraph also has to contain the different routes for the BottomNavigationBar.
How should I approach this? I am sorry if this has already been answered, I couldn't find anything about this particular case.
I think the login screen/flow must be part of the application navigation flow. In summary, your application must react to a isLoggedIn state, which should be global, and in case of the user is not logged in, the login screen must be displayed.
This is what I did:
#Composable
fun MainNavigation(
viewModel: MainViewModel,
navController: NavHostController,
) {
val auth = viewModel.auth
val initialRoute =
if (auth.isLoggedIn()) BooksFeature.route else LoginFeature.route
AnimatedNavHost(
navController,
startDestination = initialRoute
) {
loginGraph(auth, navController)
booksGraph(auth, navController)
settingsGraph(navController)
}
}
The MainNavigation composable is the root of my app (which is called in setContent at MainActivity). Each feature of the app has a navigation graph. Like booksGraph:
fun NavGraphBuilder.booksGraph(
auth: Auth, // this is a simple class which
// knows if the user is logged in
navController: NavHostController
) {
navigation(
route = BooksFeature.route,
startDestination = BooksList.route,
) {
composable("ScreenA") {
ScreenA()
}
...
}
}
In my activity (I'm using just one activity), I'm observing the login state and redirecting to the login screen properly.
private fun launchLoginObserver() {
lifecycleScope.launch(Dispatchers.Main) {
mainViewModel.isLoggedIn.collect { isLoggedInState ->
if (isLoggedInState == false) {
navigationController.navigate(LoginScreen.route) {
popUpTo(0) // reset stack
}
}
}
}
}
If you want to take a look into the full implementation, here is the link for my repository.

How to do webix jet navigation?

I am getting an error in webix jet when I navigate the URL.
The first URL is this => http://localhost:8080/#!/navigationBar/topSideBar/appslist
There is a button to call the next view, After I click the button next view URL(second URL) will => http://localhost:8080/#!/navigationBar/qtoApplication
Then, when I go back(by browser back button) to the first URL view, I got the below error, Url is changed but the view is not changing. I cannot go back to the first URL view.
I tried to add a button at the second URL view in order to go back to the first URL. It is also got the same error as per below.
I used navigationBar view as a top view, the rest is a subview.
I would like to know How to do correct navigation.
Thanks in Advance
myapp.js:9836 TypeError: Cannot read property 'linkInput' of undefined
at result._init_onchange (webix.js:30753)
at result.callEvent (webix.js:729)
at result.render (webix.js:2736)
at result.render (webix.js:28077)
at result.$setSize (webix.js:30618)
at result._set_child_size (webix.js:20648)
at result._set_child_size (webix.js:20752)
at result.$setSize (webix.js:20743)
at result._set_child_size (webix.js:20635)
at result._set_child_size (webix.js:20752)
myapp is like this,
// myapp.js
import { JetApp, EmptyRouter, HashRouter } from "webix-jet";
export default class MyApp extends JetApp {
constructor(config) {
const defaults = {
router: BUILD_AS_MODULE ? EmptyRouter : HashRouter,
debug: !PRODUCTION,
start: "/navigationBar/topSideBar/projects"
};
super({ ...defaults, ...config });
}
}
if (!BUILD_AS_MODULE) {
webix.ready(() => {
if (webix.CustomScroll){
webix.CustomScroll.init();
}
new MyApp().render();
});
}

ionic 5 Modal shows blank page on iOS

I have an issue with showing a Modal on Ionic 5 Angular 8 on iOS.
So I have a page with two buttons, one is declared in the same page component, the other one is from a child component.
When the button in the same page is clicked, the modal opens fine.
When the button from the child component is clicked, the event is emitted to the parent Page, which then creates the modal, but the modal slides up, outside the view port.
I have tried all possible trouble shooting I can think of:
Removing all custom CSS, removing all html, changing the route of the event, adding a timeout etc..
I don't have any autofocus or bootstrap: [] in my entire app.
Here is what the page looks like
export class MyPage implements OnInit, OnDestroy {
//...
private openModal (params) {
const obj = {
component: ModalComponent,
componentProps: params
};
this.modalProvider.create (obj).then (
modal => {
modal.onDidDismiss().then(
() => {}
);
modal.presente ();
}
)
}
public onOpenModal () {
const params = {
//custom properties
}
this.openModal(params);
}
public localAction () {
const params = {
// custom params
}
this.openModal (params)
}
}
Now on the template side :
<ion-content force-overscroll="false" [scrollY]="false">
<!-- Some html --->
<ion-grid (click)="localAction()">
<!-- Some html --->
</ion-grid>
<!-- Some html --->
<child-component (modalOpenEmitter)="onOpenModal($event)">
</ion-content>
Ok I have found the problem after several hours digging.
It turns out it was because of the child component which host a list of button scrolling horizontally.
When a button from the the child component was clicked, an event was emitted as per normal, but I was using a DOM function called scrollintoview like so:
Child component.ts :
public btnClicked (value) {
//...
this.clickEmitter.emit(value); // Normal stuff
const element = document.getElementById(value.id);
if (element) {
element.scrollIntoView(); // This caused the the modal to disappear
}
}
This scrollIntoView was there to make the clicked button slide further in the view port.
Unfortunately, this beaks the modal on iOS, but it works fine on android by the way.

Access navigation pane from stacked page

I'm new to Blackberry Cascades and I want to create a simple NavigationPane. I'm very used to Qt's StackView which allouse you to push and pop pages to and from the stack. However, Qt's [StackView][1] has this attached property called Stack.view which allows you to access the stack from any child page.
How can I do this in Blackberry's Cascades? Is it possible to access the NavigationPane stack of pages from the current page you're in? I see this extremely useful.
For example I have this simple project with two qml files each representing one page:
Main page:
// main.qml
import bb.cascades 1.4
NavigationPane {
id: nav
Page {
Container {
ListView {
dataModel: XmlDataModel {
source: "data.xml"
}
onTriggered: {
if (indexPath.length > 1) {
var chosenItem = dataModel.data(indexPath);
var contentpage = itemPageDefinition.createObject();
contentpage.itemPageTitle = chosenItem.name
nav.push(contentpage);
}
}
accessibility.name: "Listing"
}
}
}
attachedObjects: [
ComponentDefinition {
id: itemPageDefinition
source: "ItemPage.qml"
}
]
onPopTransitionEnded: {
page.destroy();
}
}
Secondary page:
// ItemPage.qml
import bb.cascades 1.4
Page {
property alias itemPageTitle: titlebar.title
titleBar: TitleBar {
id: titlebar
}
content: Container {
}
}
Is it possible to access nav or NavigationPane from ItemPage.qml? I would like e.g. to create a new page from ItemPage.qml and push it on the stack. Is it possible to do so?
EDIT:
For example there is this documentation page on the Blackberry developers website which has this example with a main page:
and a secondary page:
As you can see, in the secondary myPage.qml he uses the navigationPane. How is that possible? How does he have access to an ID present in another component?

Anyway to have an onLoad function in qml when adding to NavigationPane?

I'm new to Blackberry 10 dev. So I'm wondering what's the best way to do this as I'm not getting any clear answers from the dev docs.
What I want is to start a separate view in my app from a navigation screen. The new page will then create a http request and update the UI based on the output.
The best way seems to be using the NavigationPane and add a qml view. However how do I invoke a C++ function when it's pushed onto the stack? Something similar to android onActivityCreated() in Fragments. There is the Http example docs, but the program started the http request from the constructor of the inherited QObject.
How to I have a function executed as the new qml is added to the navigation stack as
// navigationpane.qml
NavigationPane {
id: navigationPane
Page {
Container {
Label {
text: "First page"
}
}
actions: [
ActionItem {
title: "Next page"
ActionBar.placement: ActionBarPlacement.OnBar
onTriggered: {
var page = pageDefinition.createObject();
navigationPane.push(page);
}
attachedObjects: ComponentDefinition {
id: pageDefinition;
source: "secondpage.qml"
}
}
]
}
onPopTransitionEnded: { page.destroy(); }
}
I think the onCreationCompleted function may be what you're looking for.
In the Page object of your secondpage.qml file, add this:
Page {
id: secondpage
onCreationCompleted: {
// use Javascript to call the exposed C++ function
}
}
If you want something more in the spirit of "onActivityCreated()", you can use the signal transitionEnded:
NavigationPane {
onPushTransitionEnded{
top.callYourPageFunction();
}
}

Resources