Skip to content

🚦 Nested routing, page controller lifecycle, and more

Compare
Choose a tag to compare
@MihaelIsaev MihaelIsaev released this 14 Mar 00:36
· 27 commits to master since this release

FragmentRouter

We may not want to replace the entire content on the page for the next route, but only certain blocks.
This is where the new FragmentRouter comes in handy!

Let's consider that we have tabs on the /user page. Each tab is a subroute, and we want to react to changes in the subroute using the FragmentRouter without reloading use page even though url changes.

Declare the top-level route in the App class

Page("user") { UserPage() }

And declare FragmentRouter in the UserPage class

class UserPage: PageController {
    @DOM override var body: DOM.Content {
        // NavBar is from Materialize library :)
        Navbar()
            .item("Profile") { self.changePath(to: "/user/profile") }
            .item("Friends") { self.changePath(to: "/user/friends") }
        FragmentRouter(self)
            .routes {
                Page("profile") { UserProfilePage() }
                Page("friends") { UserFriendsPage() }
            }
    }
}

In the example above FragmentRouter handles /user/profile and /user/friends subroutes and renders it under the Navbar, so page never reload the whole content but only specific fragments. There are also may be declared more than one fragment with the same or different subroutes and they all will just work together like a magic!

Btw FragmentRouter is a Div and you may configure it by calling

FragmentRouter(self)
    .configure { div in
        // do anything you want with the div
    }

Breaking changes

ViewController has been renamed into PageController , Xcode will propose to rename it automatically.

PageController

PageController now have lifecycle methods: willLoad, didLoad, willUnload, didUnload.

override func willLoad(with req: PageRequest) {
    super.willLoad(with: req)
}
override func didLoad(with req: PageRequest) {
    super.didLoad(with: req)
    // set page title and metaDescription
    // also parse query and hash
}
override func willUnload() {
    super.willUnload()
}
override func didUnload() {
    super.didUnload()
}

Also you can declare same methods without overriding, e.g. when you declare little page without subclassing

 PageController { page in
    H1("Hello world")
    P("Text under title")
    Button("Click me") {
        page.alert("Click!")
        print("button clicked")
    }
}
.backgroundcolor(.lightGrey)
.onWillLoad { page in }
.onDidLoad { page in }
.onWillUnload { page in }
.onDidUnload { page in }

New convenience methods

alert(message: String) - direct JS alert method
changePath(to: String) - switching URL path

More

Id and Class now can be initialized simply with string like this

Class("myClass")
Id("myId")

Tiny little change but may be very useful.

App.current.window.document.querySelectorAll("your_query") now works!

Tip

🚨Please don't forget to update Webber CLI tool to version 1.6.1 or above!