Skip to content

Commit 2379ea3

Browse files
committed
docs: App & AppBuilder comments
1 parent 1769a5c commit 2379ea3

File tree

5 files changed

+118
-22
lines changed

5 files changed

+118
-22
lines changed

src/vdom.rs

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ where
151151
pub update: UpdateFn<Ms, Mdl, ElC, GMs>,
152152
pub sink: Option<SinkFn<Ms, Mdl, ElC, GMs>>,
153153
view: ViewFn<Mdl, ElC>,
154-
window_events: Option<WindowEvents<Ms, Mdl>>,
154+
window_events: Option<WindowEventsFn<Ms, Mdl>>,
155155
}
156156

157157
pub struct UndefinedGMsg;
@@ -200,6 +200,33 @@ impl<Ms, Mdl, ElC: View<Ms> + 'static, GMs: 'static> App<Ms, Mdl, ElC, GMs> {
200200
Self::builder(update, view).init(Box::new(init))
201201
}
202202

203+
/// Creates a new `AppBuilder` instance. It's the standard way to create a Seed app.
204+
///
205+
/// Then you can call optional builder methods like `routes` or `sink`.
206+
/// And you have to call method `build_and_start` to build and run a new `App` instance.
207+
///
208+
/// _NOTE:_ If your `Model` doesn't implement `Default`, you have to call builder method `after_mount`.
209+
///
210+
/// # Example
211+
///
212+
/// ```rust,no_run
213+
/// fn update(msg: Msg, model: &mut Model, _orders: &mut impl Orders<Msg, GMsg>) {
214+
/// match msg {
215+
/// Msg::Clicked => model.clicks += 1,
216+
/// }
217+
///}
218+
///
219+
/// fn view(model: &Model) -> impl View<Msg> {
220+
/// vec![
221+
/// button![
222+
/// format!("Clicked: {}", model.clicks),
223+
/// simple_ev(Ev::Click, Msg::Clicked),
224+
/// ],
225+
/// ]
226+
///}
227+
///
228+
///App::builder(update, view)
229+
/// ```
203230
pub fn builder(
204231
update: UpdateFn<Ms, Mdl, ElC, GMs>,
205232
view: ViewFn<Mdl, ElC>,
@@ -222,7 +249,7 @@ impl<Ms, Mdl, ElC: View<Ms> + 'static, GMs: 'static> App<Ms, Mdl, ElC, GMs> {
222249
view: ViewFn<Mdl, ElC>,
223250
mount_point: Element,
224251
routes: Option<RoutesFn<Ms>>,
225-
window_events: Option<WindowEvents<Ms, Mdl>>,
252+
window_events: Option<WindowEventsFn<Ms, Mdl>>,
226253
init_cfg: OptDynInitCfg<Ms, Mdl, ElC, GMs>,
227254
) -> Self {
228255
let window = util::window();

src/vdom/alias.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@ pub type UpdateFn<Ms, Mdl, ElC, GMs> = fn(Ms, &mut Mdl, &mut OrdersContainer<Ms,
44
pub type SinkFn<Ms, Mdl, ElC, GMs> = fn(GMs, &mut Mdl, &mut OrdersContainer<Ms, Mdl, ElC, GMs>);
55
pub type ViewFn<Mdl, ElC> = fn(&Mdl) -> ElC;
66
pub type RoutesFn<Ms> = fn(routing::Url) -> Option<Ms>;
7-
pub type WindowEvents<Ms, Mdl> = fn(&Mdl) -> Vec<events::Listener<Ms>>;
7+
pub type WindowEventsFn<Ms, Mdl> = fn(&Mdl) -> Vec<events::Listener<Ms>>;
88
pub type MsgListeners<Ms> = Vec<Box<dyn Fn(&Ms)>>;

src/vdom/builder.rs

Lines changed: 63 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -346,13 +346,13 @@ impl InitAPIData for UndefinedInitAPI {
346346
}
347347
}
348348

349-
/// Used to create and store initial app configuration, ie items passed by the app creator
349+
/// Used to create and store initial app configuration, ie items passed by the app creator.
350350
pub struct Builder<Ms: 'static, Mdl: 'static, ElC: View<Ms>, GMs, InitAPIType> {
351351
update: UpdateFn<Ms, Mdl, ElC, GMs>,
352352
view: ViewFn<Mdl, ElC>,
353353

354354
routes: Option<RoutesFn<Ms>>,
355-
window_events: Option<WindowEvents<Ms, Mdl>>,
355+
window_events: Option<WindowEventsFn<Ms, Mdl>>,
356356
sink: Option<SinkFn<Ms, Mdl, ElC, GMs>>,
357357

358358
// TODO: Remove when removing legacy init fields.
@@ -443,6 +443,19 @@ impl<
443443
}
444444
}
445445

446+
/// Select HTML element where the app will be mounted and how it'll be mounted.
447+
///
448+
/// See `BeforeMount::mount_point` and `BeforeMount::mount_type` docs for more info.
449+
///
450+
/// # Example
451+
///
452+
/// ```rust,no_run
453+
///fn before_mount(_url: Url) -> BeforeMount {
454+
/// BeforeMount::new()
455+
/// .mount_point("main")
456+
/// .mount_type(MountType::Takeover)
457+
///}
458+
/// ```
446459
pub fn before_mount(
447460
self,
448461
before_mount: impl FnOnce(routing::Url) -> BeforeMount + 'static,
@@ -459,10 +472,22 @@ impl<
459472
}
460473
}
461474

462-
pub fn after_mount<NewIAM: 'static + IntoAfterMount<Ms, Mdl, ElC, GMs>>(
475+
/// You can create your `Model` and handle initial URL in this method.
476+
///
477+
/// See `AfterMount::url_handling` for more info about initial URL handling.
478+
///
479+
/// # Example
480+
///
481+
/// ```rust,no_run
482+
///fn after_mount(_url: Url, _orders: &mut impl Orders<Msg, GMsg>) -> AfterMount<Model> {
483+
/// let model = Model { clicks: 0 };
484+
/// AfterMount::new(model).url_handling(UrlHandling::None)
485+
///}
486+
/// ```
487+
pub fn after_mount<AM: 'static + IntoAfterMount<Ms, Mdl, ElC, GMs>>(
463488
self,
464-
after_mount: NewIAM,
465-
) -> Builder<Ms, Mdl, ElC, GMs, BeforeAfterInitAPI<NewIAM>> {
489+
after_mount: AM,
490+
) -> Builder<Ms, Mdl, ElC, GMs, BeforeAfterInitAPI<AM>> {
466491
Builder {
467492
update: self.update,
468493
view: self.view,
@@ -476,13 +501,34 @@ impl<
476501
}
477502

478503
/// Registers a function which maps URLs to messages.
504+
///
505+
/// When you return `None`, Seed doesn't call your `update` function
506+
/// and also doesn't push the new route or prevent page refresh.
507+
/// It's useful if the user clicked on a link and Seed shouldn't intercept it,
508+
/// because it's e.g. a download link.
509+
///
510+
/// # Example
511+
///
512+
/// ```rust,no_run
513+
///fn routes(url: Url) -> Option<Msg> {
514+
/// Some(Msg::UrlChanged(url))
515+
///}
516+
/// ```
479517
pub fn routes(mut self, routes: RoutesFn<Ms>) -> Self {
480518
self.routes = Some(routes);
481519
self
482520
}
483521

484522
/// Registers a function which decides how window events will be handled.
485-
pub fn window_events(mut self, window_events: WindowEvents<Ms, Mdl>) -> Self {
523+
///
524+
/// # Example
525+
///
526+
/// ```rust,no_run
527+
///fn window_events(_model: &Model) -> Vec<Listener<Msg>> {
528+
/// vec![keyboard_ev(Ev::KeyDown, Msg::KeyPressed)]
529+
///}
530+
/// ```
531+
pub fn window_events(mut self, window_events: WindowEventsFn<Ms, Mdl>) -> Self {
486532
self.window_events = Some(window_events);
487533
self
488534
}
@@ -492,6 +538,16 @@ impl<
492538
/// The sink function is a function which can update the model based
493539
/// on global messages. Consider to use a sink function when a
494540
/// submodule needs to trigger changes in other modules.
541+
///
542+
/// # Example
543+
///
544+
/// ```rust,no_run
545+
///fn sink(g_msg: GMsg, _model: &mut Model, _orders: &mut impl Orders<Msg, GMsg>) {
546+
/// match g_msg {
547+
/// GMsg::SayHello => log!("Hello!"),
548+
/// }
549+
///}
550+
/// ```
495551
pub fn sink(mut self, sink: SinkFn<Ms, Mdl, ElC, GMs>) -> Self {
496552
self.sink = Some(sink);
497553
self
@@ -506,7 +562,7 @@ impl<
506562
InitAPIType: InitAPI<Ms, Mdl, ElC, GMs, Builder = Self>,
507563
> Builder<Ms, Mdl, ElC, GMs, InitAPIType>
508564
{
509-
/// Build and run the app.
565+
/// Build, mount and start the app.
510566
pub fn build_and_start(self) -> App<Ms, Mdl, ElC, GMs> {
511567
InitAPIType::build(self).run()
512568
}

src/vdom/builder/after_mount.rs

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,23 +30,17 @@ pub struct AfterMount<Mdl> {
3030
}
3131

3232
impl<Mdl> AfterMount<Mdl> {
33+
/// Creates a new `AfterMount` instance. You can also use `AfterMount::default`
34+
/// if your `Model` implements `Default`.
3335
pub fn new(model: Mdl) -> Self {
3436
Self {
3537
model,
3638
url_handling: UrlHandling::default(),
3739
}
3840
}
3941

40-
// TODO: Change to const fn when possible.
41-
// TODO: Relevant issue: https://github.com/rust-lang/rust/issues/60964
42-
#[allow(clippy::missing_const_for_fn)]
43-
pub fn model<NewMdl>(self, model: NewMdl) -> AfterMount<NewMdl> {
44-
AfterMount {
45-
model,
46-
url_handling: self.url_handling,
47-
}
48-
}
49-
42+
/// - `UrlHandling::PassToRoutes` - your function `routes` will be called with initial URL. _[Default]_
43+
/// - `UrlHandling::None` - URL won't be handled by Seed.
5044
pub const fn url_handling(mut self, url_handling: UrlHandling) -> Self {
5145
self.url_handling = url_handling;
5246
self

src/vdom/builder/before_mount.rs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,21 +61,40 @@ impl Default for MountType {
6161

6262
pub struct BeforeMount {
6363
pub(crate) mount_point_getter: Box<dyn FnOnce() -> Element>,
64-
/// How to handle elements already present in the mount. Defaults to [`MountType::Append`]
65-
/// in the constructors.
64+
/// How to handle elements already present in the mount.
65+
/// Defaults to `MountType::Append` in the constructors.
6666
pub(crate) mount_type: MountType,
6767
}
6868

6969
impl BeforeMount {
70+
/// Creates a new `BeforeMount` instance. It's the alias for `BeforeMount::default`.
7071
pub fn new() -> Self {
7172
Self::default()
7273
}
7374

75+
/// Choose the element where the application will be mounted.
76+
/// The default one is the element with `id` = "app".
77+
///
78+
/// # Examples
79+
///
80+
/// ```rust,no_run
81+
/// // argument is `&str`
82+
/// mount_point("another_id")
83+
///
84+
/// // argument is `HTMLElement`
85+
/// // NOTE: Be careful with mounting into body,
86+
/// // it can cause hard-to-debug bugs when there are other scripts in the body.
87+
/// mount_point(seed::body())
88+
///
89+
/// // argument is `Element`
90+
/// mount_point(seed::body().querySelector("section").unwrap().unwrap())
91+
/// ```
7492
pub fn mount_point(mut self, mount_point: impl MountPoint + 'static) -> BeforeMount {
7593
self.mount_point_getter = Box::new(mount_point.element_getter());
7694
self
7795
}
7896

97+
/// How to handle elements already present in the mount point. Defaults to `MountType::Append`.
7998
pub const fn mount_type(mut self, mount_type: MountType) -> Self {
8099
self.mount_type = mount_type;
81100
self

0 commit comments

Comments
 (0)