Skip to main content

link

Struct link 

Source
pub struct link<H>(pub PhantomData<(H,)>)
where
    H: AttributeValueViewParts + Send;
Expand description

A link that opens a page without reloading the whole document. The server renders the destination and the runtime updates the current document with the result.

Use link inside a view, with href! pointing to a page in your app:

use topcoat::{
    Result,
    router::{href, page},
    runtime::link,
    view::{View, view},
};

#[page]
async fn home() -> Result<impl View> {
    Ok(view! {
        link(href: href!(about::page), "About")
    })
}

mod about {
    use super::*;

    #[page]
    pub async fn page() -> Result<impl View> {
        Ok(view! { <h1>"About"</h1> })
    }
}

With module routing, this links to /about. Enable .runtime() on the router, load the asset bundle, and include topcoat::runtime::script() in the document head. See the runtime setup guide for the full setup.

The component renders an ordinary <a>, so the link also works without JavaScript. Use a plain <a href=(href!(about::page))> when you want a normal page load.

§Prefetching

By default, a link starts loading its destination after a brief hover, on focus, or on touch. This is PrefetchMode::Intent. When the user follows the link, navigation can reuse that response even if it is still arriving.

Set prefetch on a link to choose when its destination loads:

use topcoat::{
    router::href,
    runtime::{PrefetchMode, link},
    view::view,
};
Ok(view! {
    link(href: href!(products), prefetch: PrefetchMode::Viewport, "Products")
    link(href: href!(reports), prefetch: PrefetchMode::Never, "Reports")
})

Viewport loads the destination when the link comes into view. Never waits until the user follows the link, while still navigating without a full reload. Prefetching is best effort; the runtime may skip it when the browser is set to save data or other prefetch requests are still loading.

Prefetching renders the destination on the server even if the user never opens it. Keep mutations in form submissions or procedures rather than page rendering.

Set the default for the app with RouterBuilderRuntimeExt::prefetch:

use topcoat::{
    router::Router,
    runtime::{PrefetchMode, RouterBuilderRuntimeExt},
};

let router = Router::builder()
    .runtime()
    .prefetch(PrefetchMode::Viewport)
    .build();

To choose a default for part of a page, add a PrefetchMode to its context:

use topcoat::{
    context::Cx,
    router::href,
    runtime::{PrefetchMode, link},
    view::{View, view},
};

fn reports_nav(cx: &Cx) -> impl View {
    let cx = cx.with(PrefetchMode::Never);
    view! { cx =>
        link(href: href!(reports), "Reports")
    }
}

A link’s prefetch argument takes precedence over the request context, then the app context, then Intent. prefetch_mode returns the default for a context.

§Custom Anchors

Pass attrs to add classes and other HTML attributes:

Ok(view! {
    link(
        href: href!(products),
        attrs: attributes! { class="nav-link" },
        "Products"
    )
})

The href and prefetch arguments override matching attributes in attrs. The link’s children can contain any view content.

For your own <a> markup, use link_attrs to create the destination and navigation attributes, then spread them onto the anchor:

use topcoat::{
    context::Cx,
    router::href,
    runtime::{link_attrs, prefetch_mode},
    view::{View, view},
};

fn products_link(cx: &Cx) -> impl View {
    let attrs = link_attrs(cx, href!(products), prefetch_mode(cx));
    view! { cx =>
        <a class="product-card" (attrs)>
            <strong>"Browse products"</strong>
            <span>"See what's new"</span>
        </a>
    }
}

The current page stays visible until the destination’s initial HTML arrives. The runtime updates the document, including its title, then applies any streamed content that follows. Signals declared on both pages keep their values. This lets shared components retain state across navigation.

Navigation updates the address bar and browser history. New pages scroll to the top, or to the target of a URL fragment. Back and forward navigation restore saved scroll positions. Links to fragments on the current page use the browser’s normal behavior.

Modifier clicks, downloads, external links, and links targeting another window or frame also retain their normal browser behavior. If a destination needs scripts that have not been loaded, or its response cannot be used for runtime navigation, the browser loads the page normally.

Tuple Fields§

§0: PhantomData<(H,)>

Trait Implementations§

Source§

impl<H> Component for link<H>

Source§

type Props<'__props> = LinkProps<'__props, H>

The component’s properties. The lifetime covers data borrowed from the caller.
Source§

fn render<'__a, '__props>( self, cx: &'__a Cx, props: Self::Props<'__props>, ) -> impl Future<Output = Result<impl View>> + Send + '__a
where Self: '__a, Self::Props<'__props>: '__a, '__props: '__a,

Renders the component to a View. Read more
Source§

fn props_builder<'a>() -> <Self::Props<'a> as Props>::Builder

Source§

impl<H> Default for link<H>

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

§

impl<H> Freeze for link<H>

§

impl<H> RefUnwindSafe for link<H>

§

impl<H> Send for link<H>

§

impl<H> Sync for link<H>

§

impl<H> Unpin for link<H>

§

impl<H> UnsafeUnpin for link<H>

§

impl<H> UnwindSafe for link<H>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more