updates toward `todo_app_sqlite`
This commit is contained in:
parent
e837e9fded
commit
a01640cafd
|
@ -14,8 +14,6 @@ http = "1.0"
|
|||
leptos = { path = "../../leptos" }
|
||||
server_fn = { path = "../../server_fn", features = ["serde-lite"] }
|
||||
leptos_axum = { path = "../../integrations/axum", optional = true }
|
||||
leptos_meta = { path = "../../meta" }
|
||||
leptos_router = { path = "../../router" }
|
||||
log = "0.4"
|
||||
simple_logger = "4.0"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
use crate::errors::TodoAppError;
|
||||
use leptos::*;
|
||||
use leptos::context::use_context;
|
||||
use leptos::signals::RwSignal;
|
||||
use leptos::{component, server, view, For, IntoView};
|
||||
use leptos::{prelude::*, Errors};
|
||||
#[cfg(feature = "ssr")]
|
||||
use leptos_axum::ResponseOptions;
|
||||
|
||||
|
@ -8,10 +11,10 @@ use leptos_axum::ResponseOptions;
|
|||
#[component]
|
||||
pub fn ErrorTemplate(
|
||||
#[prop(optional)] outside_errors: Option<Errors>,
|
||||
#[prop(optional)] errors: Option<RwSignal<Errors>>,
|
||||
#[prop(optional, into)] errors: Option<RwSignal<Errors>>,
|
||||
) -> impl IntoView {
|
||||
let errors = match outside_errors {
|
||||
Some(e) => create_rw_signal(e),
|
||||
Some(e) => RwSignal::new(e),
|
||||
None => match errors {
|
||||
Some(e) => e,
|
||||
None => panic!("No Errors found and we expected errors!"),
|
||||
|
|
|
@ -5,7 +5,8 @@ use axum::{
|
|||
http::{Request, Response, StatusCode, Uri},
|
||||
response::{IntoResponse, Response as AxumResponse},
|
||||
};
|
||||
use leptos::{view, Errors, LeptosOptions};
|
||||
use leptos::config::LeptosOptions;
|
||||
use leptos::{view, Errors};
|
||||
use tower::ServiceExt;
|
||||
use tower_http::services::ServeDir;
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ pub mod errors;
|
|||
pub mod fallback;
|
||||
pub mod todo;
|
||||
|
||||
#[cfg(feature = "hydrate")]
|
||||
#[wasm_bindgen::prelude::wasm_bindgen]
|
||||
pub fn hydrate() {
|
||||
use crate::todo::TodoApp;
|
||||
|
@ -11,5 +12,5 @@ pub fn hydrate() {
|
|||
_ = console_log::init_with_level(log::Level::Error);
|
||||
console_error_panic_hook::set_once();
|
||||
|
||||
leptos::mount_to_body(TodoApp);
|
||||
leptos::hydrate_body(TodoApp);
|
||||
}
|
||||
|
|
|
@ -7,7 +7,11 @@ use axum::{
|
|||
routing::get,
|
||||
Router,
|
||||
};
|
||||
use leptos::*;
|
||||
use leptos::{
|
||||
config::{get_configuration, LeptosOptions},
|
||||
view,
|
||||
};
|
||||
use leptos::{context::provide_context, HydrationScripts};
|
||||
use leptos_axum::{generate_route_list, LeptosRoutes};
|
||||
use todo_app_sqlite_axum::*;
|
||||
|
||||
|
@ -48,14 +52,35 @@ async fn main() {
|
|||
// build our application with a route
|
||||
let app = Router::new()
|
||||
.route("/special/:id", get(custom_handler))
|
||||
.leptos_routes(&leptos_options, routes, || view! { <TodoApp/> })
|
||||
.leptos_routes(&leptos_options, routes, {
|
||||
let leptos_options = leptos_options.clone();
|
||||
move || {
|
||||
use leptos::prelude::*;
|
||||
|
||||
view! {
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
||||
//<AutoReload options=app_state.leptos_options.clone() />
|
||||
<HydrationScripts options=leptos_options.clone()/>
|
||||
<link rel="stylesheet" id="leptos" href="/pkg/benwis_leptos.css"/>
|
||||
<link rel="shortcut icon" type="image/ico" href="/favicon.ico"/>
|
||||
</head>
|
||||
<body>
|
||||
<TodoApp/>
|
||||
</body>
|
||||
</html>
|
||||
}
|
||||
}})
|
||||
.fallback(file_and_error_handler)
|
||||
.with_state(leptos_options);
|
||||
|
||||
// run our app with hyper
|
||||
// `axum::Server` is a re-export of `hyper::Server`
|
||||
let listener = tokio::net::TcpListener::bind(&addr).await.unwrap();
|
||||
logging::log!("listening on http://{}", &addr);
|
||||
println!("listening on http://{}", &addr);
|
||||
axum::serve(listener, app.into_make_service())
|
||||
.await
|
||||
.unwrap();
|
||||
|
|
|
@ -1,9 +1,14 @@
|
|||
use crate::error_template::ErrorTemplate;
|
||||
use leptos::*;
|
||||
use leptos_meta::*;
|
||||
use leptos_router::*;
|
||||
use leptos::context::use_context;
|
||||
use leptos::server::{Resource, ServerAction};
|
||||
use leptos::tachys::either::Either;
|
||||
use leptos::{
|
||||
component, server, suspend, view, ActionForm, ErrorBoundary, IntoView,
|
||||
};
|
||||
use leptos::{prelude::*, Transition};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use server_fn::codec::SerdeLite;
|
||||
use server_fn::ServerFnError;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "ssr", derive(sqlx::FromRow))]
|
||||
|
@ -16,7 +21,7 @@ pub struct Todo {
|
|||
#[cfg(feature = "ssr")]
|
||||
pub mod ssr {
|
||||
// use http::{header::SET_COOKIE, HeaderMap, HeaderValue, StatusCode};
|
||||
use leptos::ServerFnError;
|
||||
use leptos::server_fn::ServerFnError;
|
||||
use sqlx::{Connection, SqliteConnection};
|
||||
|
||||
pub async fn db() -> Result<SqliteConnection, ServerFnError> {
|
||||
|
@ -87,82 +92,65 @@ pub async fn delete_todo(id: u16) -> Result<(), ServerFnError> {
|
|||
|
||||
#[component]
|
||||
pub fn TodoApp() -> impl IntoView {
|
||||
//let id = use_context::<String>();
|
||||
provide_meta_context();
|
||||
view! {
|
||||
<Link rel="shortcut icon" type_="image/ico" href="/favicon.ico"/>
|
||||
<Stylesheet id="leptos" href="/pkg/todo_app_sqlite_axum.css"/>
|
||||
<Router>
|
||||
<header>
|
||||
<h1>"My Tasks"</h1>
|
||||
</header>
|
||||
<main>
|
||||
<Routes>
|
||||
<Route path="" view=Todos/>
|
||||
</Routes>
|
||||
</main>
|
||||
</Router>
|
||||
<header>
|
||||
<h1>"My Tasks"</h1>
|
||||
</header>
|
||||
<main>
|
||||
<Todos/>
|
||||
</main>
|
||||
}
|
||||
}
|
||||
|
||||
#[component]
|
||||
pub fn Todos() -> impl IntoView {
|
||||
let add_todo = create_server_multi_action::<AddTodo>();
|
||||
let delete_todo = create_server_action::<DeleteTodo>();
|
||||
let submissions = add_todo.submissions();
|
||||
//let add_todo = create_server_multi_action::<AddTodo>();
|
||||
let delete_todo = ServerAction::<DeleteTodo>::new();
|
||||
//let submissions = add_todo.submissions();
|
||||
|
||||
// list of todos is loaded from the server in reaction to changes
|
||||
let todos = create_resource(
|
||||
move || (add_todo.version().get(), delete_todo.version().get()),
|
||||
let todos = Resource::new_serde(
|
||||
move || (delete_todo.version().get()), //(add_todo.version().get(), delete_todo.version().get()),
|
||||
move |_| get_todos(),
|
||||
);
|
||||
|
||||
view! {
|
||||
<div>
|
||||
<MultiActionForm action=add_todo>
|
||||
/*<MultiActionForm action=add_todo>
|
||||
<label>
|
||||
"Add a Todo"
|
||||
<input type="text" name="title"/>
|
||||
</label>
|
||||
<input type="submit" value="Add"/>
|
||||
</MultiActionForm>
|
||||
</MultiActionForm>*/
|
||||
<Transition fallback=move || view! {<p>"Loading..."</p> }>
|
||||
<ErrorBoundary fallback=|errors| view!{<ErrorTemplate errors=errors/>}>
|
||||
{move || {
|
||||
let existing_todos = {
|
||||
move || {
|
||||
todos.get()
|
||||
.map(move |todos| match todos {
|
||||
Err(e) => {
|
||||
view! { <pre class="error">"Server Error: " {e.to_string()}</pre>}.into_view()
|
||||
}
|
||||
Ok(todos) => {
|
||||
if todos.is_empty() {
|
||||
view! { <p>"No tasks were found."</p> }.into_view()
|
||||
} else {
|
||||
todos
|
||||
.into_iter()
|
||||
.map(move |todo| {
|
||||
view! {
|
||||
|
||||
<li>
|
||||
{todo.title}
|
||||
<ActionForm action=delete_todo>
|
||||
<input type="hidden" name="id" value={todo.id}/>
|
||||
<input type="submit" value="X"/>
|
||||
</ActionForm>
|
||||
</li>
|
||||
}
|
||||
})
|
||||
.collect_view()
|
||||
<ErrorBoundary fallback=|errors| view!{<ErrorTemplate errors/>}>
|
||||
<ul>
|
||||
{suspend!(
|
||||
todos.await.map(|todos| {
|
||||
if todos.is_empty() {
|
||||
Either::Left(view! { <p>"No tasks were found."</p> })
|
||||
} else {
|
||||
Either::Right(todos
|
||||
.into_iter()
|
||||
.map(move |todo| {
|
||||
view! {
|
||||
<li>
|
||||
{todo.title}
|
||||
<ActionForm action=delete_todo>
|
||||
<input type="hidden" name="id" value={todo.id}/>
|
||||
<input type="submit" value="X"/>
|
||||
</ActionForm>
|
||||
</li>
|
||||
}
|
||||
}
|
||||
})
|
||||
.unwrap_or_default()
|
||||
}
|
||||
};
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
)
|
||||
}
|
||||
})
|
||||
)}
|
||||
|
||||
let pending_todos = move || {
|
||||
/*let pending_todos = move || {
|
||||
submissions
|
||||
.get()
|
||||
.into_iter()
|
||||
|
@ -173,18 +161,12 @@ pub fn Todos() -> impl IntoView {
|
|||
<li class="pending">{move || submission.input.get().map(|data| data.title) }</li>
|
||||
}
|
||||
})
|
||||
.collect_view()
|
||||
};
|
||||
.collect::<Vec<_>>()
|
||||
};*/
|
||||
|
||||
view! {
|
||||
|
||||
<ul>
|
||||
{existing_todos}
|
||||
{pending_todos}
|
||||
</ul>
|
||||
}
|
||||
}
|
||||
}
|
||||
// {existing_todos}
|
||||
//{pending_todos}
|
||||
</ul>
|
||||
</ErrorBoundary>
|
||||
</Transition>
|
||||
</div>
|
||||
|
|
|
@ -1435,7 +1435,7 @@ where
|
|||
additional_context();
|
||||
RouteList::generate(&app_fn)
|
||||
})
|
||||
.expect("could not generate routes");
|
||||
.unwrap_or_default();
|
||||
|
||||
// Axum's Router defines Root routes as "/" not ""
|
||||
let mut routes = routes
|
||||
|
|
|
@ -27,7 +27,7 @@ paste = "1"
|
|||
rand = { version = "0.8", optional = true }
|
||||
reactive_graph = { workspace = true, features = ["serde"] }
|
||||
rustc-hash = "1"
|
||||
tachys = { workspace = true, features = ["reactive_graph"] }
|
||||
tachys = { workspace = true, features = ["reactive_graph", "oco"] }
|
||||
thiserror = "1"
|
||||
tracing = "0.1"
|
||||
typed-builder = "0.18"
|
||||
|
@ -86,7 +86,7 @@ rkyv = ["leptos_reactive/rkyv", "server_fn/rkyv"]
|
|||
tracing = [
|
||||
"reactive_graph/tracing",
|
||||
] #, "leptos_macro/tracing", "leptos_dom/tracing"]
|
||||
nonce = ["leptos_dom/nonce"]
|
||||
nonce = ["base64", "leptos_dom/nonce", "rand"]
|
||||
spin = ["leptos_reactive/spin", "leptos-spin-macro"]
|
||||
experimental-islands = [
|
||||
"leptos_dom/experimental-islands",
|
||||
|
|
|
@ -115,7 +115,16 @@ where
|
|||
const MIN_LENGTH: usize = Chil::MIN_LENGTH;
|
||||
|
||||
fn to_html_with_buf(self, buf: &mut String, position: &mut Position) {
|
||||
todo!()
|
||||
self.fallback.to_html_with_buf(buf, position);
|
||||
}
|
||||
|
||||
fn to_html_async_with_buf<const OUT_OF_ORDER: bool>(
|
||||
self,
|
||||
buf: &mut StreamBuilder,
|
||||
position: &mut Position,
|
||||
) where
|
||||
Self: Sized,
|
||||
{
|
||||
}
|
||||
|
||||
fn hydrate<const FROM_SERVER: bool>(
|
||||
|
|
|
@ -2,11 +2,11 @@ use crate::ServerMetaContext;
|
|||
use indexmap::IndexMap;
|
||||
use leptos::{
|
||||
component,
|
||||
error::Result,
|
||||
oco::Oco,
|
||||
reactive_graph::{effect::RenderEffect, owner::use_context},
|
||||
tachys::{
|
||||
dom::document,
|
||||
error::Result,
|
||||
html::{
|
||||
attribute::{
|
||||
any_attribute::{
|
||||
|
@ -96,6 +96,7 @@ struct BodyViewState {
|
|||
impl Render<Dom> for BodyView {
|
||||
type State = BodyViewState;
|
||||
type FallibleState = BodyViewState;
|
||||
type AsyncOutput = Self;
|
||||
|
||||
fn build(self) -> Self::State {
|
||||
let el = document().body().expect("there to be a <body> element");
|
||||
|
@ -121,6 +122,10 @@ impl Render<Dom> for BodyView {
|
|||
self.rebuild(state);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn resolve(self) -> Self {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderHtml<Dom> for BodyView {
|
||||
|
|
|
@ -2,11 +2,11 @@ use crate::ServerMetaContext;
|
|||
use indexmap::IndexMap;
|
||||
use leptos::{
|
||||
component,
|
||||
error::Result,
|
||||
oco::Oco,
|
||||
reactive_graph::{effect::RenderEffect, owner::use_context},
|
||||
tachys::{
|
||||
dom::document,
|
||||
error::Result,
|
||||
html::{
|
||||
attribute::{
|
||||
self,
|
||||
|
@ -107,6 +107,7 @@ struct HtmlViewState {
|
|||
impl Render<Dom> for HtmlView {
|
||||
type State = HtmlViewState;
|
||||
type FallibleState = HtmlViewState;
|
||||
type AsyncOutput = Self;
|
||||
|
||||
fn build(self) -> Self::State {
|
||||
let el = document()
|
||||
|
@ -134,6 +135,10 @@ impl Render<Dom> for HtmlView {
|
|||
self.rebuild(state);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn resolve(self) -> Self {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderHtml<Dom> for HtmlView {
|
||||
|
|
|
@ -165,8 +165,8 @@ impl ServerMetaContext {
|
|||
/// included.
|
||||
pub async fn inject_meta_context(
|
||||
self,
|
||||
mut stream: impl Stream<Item = String> + Send + Sync + Unpin,
|
||||
) -> impl Stream<Item = String> + Send + Sync {
|
||||
mut stream: impl Stream<Item = String> + Send + Unpin,
|
||||
) -> impl Stream<Item = String> + Send {
|
||||
let mut first_chunk = stream.next().await.unwrap_or_default();
|
||||
|
||||
let meta_buf =
|
||||
|
@ -324,6 +324,7 @@ where
|
|||
{
|
||||
type State = RegisteredMetaTagState<E, At, Ch>;
|
||||
type FallibleState = RegisteredMetaTagState<E, At, Ch>;
|
||||
type AsyncOutput = Self;
|
||||
|
||||
fn build(self) -> Self::State {
|
||||
let state = self.el.unwrap().build();
|
||||
|
@ -334,17 +335,21 @@ where
|
|||
self.el.unwrap().rebuild(&mut state.state);
|
||||
}
|
||||
|
||||
fn try_build(self) -> leptos::tachys::error::Result<Self::FallibleState> {
|
||||
fn try_build(self) -> leptos::error::Result<Self::FallibleState> {
|
||||
Ok(self.build())
|
||||
}
|
||||
|
||||
fn try_rebuild(
|
||||
self,
|
||||
state: &mut Self::FallibleState,
|
||||
) -> leptos::tachys::error::Result<()> {
|
||||
) -> leptos::error::Result<()> {
|
||||
self.rebuild(state);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn resolve(self) -> Self {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<E, At, Ch> RenderHtml<Dom> for RegisteredMetaTag<E, At, Ch>
|
||||
|
@ -435,21 +440,26 @@ struct MetaTagsView {
|
|||
impl Render<Dom> for MetaTagsView {
|
||||
type State = ();
|
||||
type FallibleState = ();
|
||||
type AsyncOutput = Self;
|
||||
|
||||
fn build(self) -> Self::State {}
|
||||
|
||||
fn rebuild(self, state: &mut Self::State) {}
|
||||
|
||||
fn try_build(self) -> leptos::tachys::error::Result<Self::FallibleState> {
|
||||
fn try_build(self) -> leptos::error::Result<Self::FallibleState> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn try_rebuild(
|
||||
self,
|
||||
state: &mut Self::FallibleState,
|
||||
) -> leptos::tachys::error::Result<()> {
|
||||
) -> leptos::error::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn resolve(self) -> Self::AsyncOutput {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderHtml<Dom> for MetaTagsView {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use crate::{use_head, MetaContext, ServerMetaContext};
|
||||
use leptos::{
|
||||
component,
|
||||
error::Result,
|
||||
oco::Oco,
|
||||
reactive_graph::{
|
||||
effect::RenderEffect,
|
||||
|
@ -8,7 +9,6 @@ use leptos::{
|
|||
},
|
||||
tachys::{
|
||||
dom::document,
|
||||
error::Result,
|
||||
hydration::Cursor,
|
||||
renderer::{dom::Dom, Renderer},
|
||||
view::{Mountable, Position, PositionState, Render, RenderHtml},
|
||||
|
@ -193,6 +193,7 @@ struct TitleViewState {
|
|||
impl Render<Dom> for TitleView {
|
||||
type State = TitleViewState;
|
||||
type FallibleState = TitleViewState;
|
||||
type AsyncOutput = Self;
|
||||
|
||||
fn build(self) -> Self::State {
|
||||
let el = self.el();
|
||||
|
@ -229,6 +230,10 @@ impl Render<Dom> for TitleView {
|
|||
self.rebuild(state);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn resolve(self) -> Self {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderHtml<Dom> for TitleView {
|
||||
|
|
|
@ -198,6 +198,13 @@ impl<T: Send + Sync + 'static> From<ArcRwSignal<T>> for RwSignal<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, T: Send + Sync + 'static> From<&'a ArcRwSignal<T>> for RwSignal<T> {
|
||||
#[track_caller]
|
||||
fn from(value: &'a ArcRwSignal<T>) -> Self {
|
||||
value.clone().into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Send + Sync + 'static> From<RwSignal<T>> for ArcRwSignal<T> {
|
||||
#[track_caller]
|
||||
fn from(value: RwSignal<T>) -> Self {
|
||||
|
|
|
@ -7,7 +7,7 @@ where
|
|||
Self: 'static,
|
||||
R: Renderer + 'static,
|
||||
{
|
||||
type Output: Render<R>;
|
||||
type Output: Render<R> + Send;
|
||||
|
||||
fn choose(self, route_data: RouteData<R>) -> Self::Output;
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ where
|
|||
impl<F, View, R> ChooseView<R> for F
|
||||
where
|
||||
F: Fn(RouteData<R>) -> View + 'static,
|
||||
View: Render<R>,
|
||||
View: Render<R> + Send,
|
||||
R: Renderer + 'static,
|
||||
{
|
||||
type Output = View;
|
||||
|
|
|
@ -91,7 +91,7 @@ where
|
|||
R: Renderer + 'static,
|
||||
{
|
||||
type Child: MatchInterface<R> + MatchParams + 'static;
|
||||
type View: Render<R> + RenderHtml<R> + 'static;
|
||||
type View: Render<R> + RenderHtml<R> + Send + 'static;
|
||||
|
||||
fn as_id(&self) -> RouteMatchId;
|
||||
|
||||
|
|
|
@ -112,7 +112,7 @@ where
|
|||
Rndr: Renderer + 'static,
|
||||
Child: MatchInterface<Rndr> + MatchParams + 'static,
|
||||
ViewFn: Fn(RouteData<Rndr>) -> View + 'static,
|
||||
View: Render<Rndr> + RenderHtml<Rndr> + 'static,
|
||||
View: Render<Rndr> + RenderHtml<Rndr> + Send + 'static,
|
||||
{
|
||||
type Child = Child;
|
||||
type View = ViewFn::Output;
|
||||
|
@ -148,7 +148,7 @@ where
|
|||
Children: 'static,
|
||||
<Children::Match as MatchParams>::Params: Clone,
|
||||
ViewFn: Fn(RouteData<Rndr>) -> View + Clone + 'static,
|
||||
View: Render<Rndr> + RenderHtml<Rndr> + 'static,
|
||||
View: Render<Rndr> + RenderHtml<Rndr> + Send + 'static,
|
||||
{
|
||||
type Data = Data;
|
||||
type View = View;
|
||||
|
|
|
@ -120,6 +120,7 @@ where
|
|||
>,
|
||||
>;
|
||||
type FallibleState = (); // TODO
|
||||
type AsyncOutput = (); // TODO
|
||||
|
||||
fn build(self) -> Self::State {
|
||||
let location = Loc::new().unwrap(); // TODO
|
||||
|
@ -176,16 +177,18 @@ where
|
|||
|
||||
fn rebuild(self, state: &mut Self::State) {}
|
||||
|
||||
fn try_build(self) -> tachys::error::Result<Self::FallibleState> {
|
||||
fn try_build(self) -> leptos::error::Result<Self::FallibleState> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn try_rebuild(
|
||||
self,
|
||||
state: &mut Self::FallibleState,
|
||||
) -> tachys::error::Result<()> {
|
||||
) -> leptos::error::Result<()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
async fn resolve(self) -> Self::AsyncOutput {}
|
||||
}
|
||||
|
||||
impl<Rndr, Loc, FallbackFn, Fallback, Children> RenderHtml<Rndr>
|
||||
|
@ -631,6 +634,7 @@ where
|
|||
{
|
||||
type State = Outlet<R>;
|
||||
type FallibleState = ();
|
||||
type AsyncOutput = Self;
|
||||
|
||||
fn build(self) -> Self::State {
|
||||
self
|
||||
|
@ -640,16 +644,20 @@ where
|
|||
todo!()
|
||||
}
|
||||
|
||||
fn try_build(self) -> tachys::error::Result<Self::FallibleState> {
|
||||
fn try_build(self) -> leptos::error::Result<Self::FallibleState> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn try_rebuild(
|
||||
self,
|
||||
state: &mut Self::FallibleState,
|
||||
) -> tachys::error::Result<()> {
|
||||
) -> leptos::error::Result<()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
async fn resolve(self) -> Self {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<R> RenderHtml<R> for Outlet<R>
|
||||
|
@ -857,6 +865,7 @@ where
|
|||
{
|
||||
type State = NestedRouteState<Matcher, R>;
|
||||
type FallibleState = ();
|
||||
type AsyncOutput = Self;
|
||||
|
||||
fn build(self) -> Self::State {
|
||||
let NestedRouteView {
|
||||
|
@ -892,16 +901,20 @@ where
|
|||
view.rebuild(&mut state.view);
|
||||
}
|
||||
|
||||
fn try_build(self) -> tachys::error::Result<Self::FallibleState> {
|
||||
fn try_build(self) -> leptos::error::Result<Self::FallibleState> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn try_rebuild(
|
||||
self,
|
||||
state: &mut Self::FallibleState,
|
||||
) -> tachys::error::Result<()> {
|
||||
) -> leptos::error::Result<()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
async fn resolve(self) -> Self {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<Matcher, R> RenderHtml<R> for NestedRouteView<Matcher, R>
|
||||
|
@ -1075,6 +1088,7 @@ where
|
|||
>,
|
||||
>;
|
||||
type FallibleState = Self::State;
|
||||
type AsyncOutput = Self;
|
||||
|
||||
fn build(self) -> Self::State {
|
||||
let location = Loc::new().unwrap(); // TODO
|
||||
|
@ -1158,16 +1172,20 @@ where
|
|||
|
||||
fn rebuild(self, state: &mut Self::State) {}
|
||||
|
||||
fn try_build(self) -> tachys::error::Result<Self::FallibleState> {
|
||||
fn try_build(self) -> leptos::error::Result<Self::FallibleState> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn try_rebuild(
|
||||
self,
|
||||
state: &mut Self::FallibleState,
|
||||
) -> tachys::error::Result<()> {
|
||||
) -> leptos::error::Result<()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
async fn resolve(self) -> Self {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<Rndr, Loc, FallbackFn, Fallback, Children> RenderHtml<Rndr>
|
||||
|
|
|
@ -1,5 +1,14 @@
|
|||
use crate::renderer::Renderer;
|
||||
use std::borrow::Cow;
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
fmt::Write,
|
||||
net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6},
|
||||
num::{
|
||||
NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8,
|
||||
NonZeroIsize, NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64,
|
||||
NonZeroU8, NonZeroUsize,
|
||||
},
|
||||
};
|
||||
|
||||
pub trait AttributeValue<R: Renderer> {
|
||||
type State;
|
||||
|
@ -326,3 +335,88 @@ where
|
|||
fn escape_attr(value: &str) -> Cow<'_, str> {
|
||||
html_escape::encode_double_quoted_attribute(value)
|
||||
}
|
||||
|
||||
macro_rules! render_primitive {
|
||||
($($child_type:ty),* $(,)?) => {
|
||||
$(
|
||||
impl<R> AttributeValue<R> for $child_type
|
||||
where
|
||||
R: Renderer,
|
||||
{
|
||||
type State = (R::Element, $child_type);
|
||||
|
||||
fn html_len(&self) -> usize {
|
||||
0
|
||||
}
|
||||
|
||||
fn to_html(self, key: &str, buf: &mut String) {
|
||||
<String as AttributeValue<R>>::to_html(self.to_string(), key, buf);
|
||||
}
|
||||
|
||||
fn to_template(_key: &str, _buf: &mut String) {}
|
||||
|
||||
fn hydrate<const FROM_SERVER: bool>(
|
||||
self,
|
||||
key: &str,
|
||||
el: &R::Element,
|
||||
) -> Self::State {
|
||||
// if we're actually hydrating from SSRed HTML, we don't need to set the attribute
|
||||
// if we're hydrating from a CSR-cloned <template>, we do need to set non-StaticAttr attributes
|
||||
if !FROM_SERVER {
|
||||
R::set_attribute(el, key, &self.to_string());
|
||||
}
|
||||
(el.clone(), self)
|
||||
}
|
||||
|
||||
fn build(self, el: &R::Element, key: &str) -> Self::State {
|
||||
R::set_attribute(el, key, &self.to_string());
|
||||
(el.to_owned(), self)
|
||||
}
|
||||
|
||||
fn rebuild(self, key: &str, state: &mut Self::State) {
|
||||
let (el, prev_value) = state;
|
||||
if self != *prev_value {
|
||||
R::set_attribute(el, key, &self.to_string());
|
||||
}
|
||||
*prev_value = self;
|
||||
}
|
||||
}
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
render_primitive![
|
||||
usize,
|
||||
u8,
|
||||
u16,
|
||||
u32,
|
||||
u64,
|
||||
u128,
|
||||
isize,
|
||||
i8,
|
||||
i16,
|
||||
i32,
|
||||
i64,
|
||||
i128,
|
||||
f32,
|
||||
f64,
|
||||
char,
|
||||
IpAddr,
|
||||
SocketAddr,
|
||||
SocketAddrV4,
|
||||
SocketAddrV6,
|
||||
Ipv4Addr,
|
||||
Ipv6Addr,
|
||||
NonZeroI8,
|
||||
NonZeroU8,
|
||||
NonZeroI16,
|
||||
NonZeroU16,
|
||||
NonZeroI32,
|
||||
NonZeroU32,
|
||||
NonZeroI64,
|
||||
NonZeroU64,
|
||||
NonZeroI128,
|
||||
NonZeroU128,
|
||||
NonZeroIsize,
|
||||
NonZeroUsize,
|
||||
];
|
||||
|
|
Loading…
Reference in New Issue