Skip to content
This repository has been archived by the owner on Jul 19, 2020. It is now read-only.

5/8 add emitevents page #86

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
334 changes: 334 additions & 0 deletions src/concepts/components/emitevents.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,334 @@
---
description: Component could share update to the parent html component emit events
---

# Emit events

It's possible to update the parent containers emitting **events** by the same way we received data via **properties**.
rlasjunies marked this conversation as resolved.
Show resolved Hide resolved

The events are defined as part of the `Properties` struct.

When it's needed you just need to call the `emit()` method of the event, to propagate the update to the parents containers.
rlasjunies marked this conversation as resolved.
Show resolved Hide resolved

> You could name the event as you want. It's usually started by "on"
rlasjunies marked this conversation as resolved.
Show resolved Hide resolved
rlasjunies marked this conversation as resolved.
Show resolved Hide resolved

```rust
use yew::prelude::*;

pub struct EmitEventComponent {
link: ComponentLink<Self>,
props: Props,
name: String,
show_message: bool,
}

pub enum Msg {
Click(),
Click4Event(),
}

#[derive(Properties, Clone, PartialEq)]
pub struct Props{
#[prop_or("Clark by default".to_string())]
pub name: String,

#[prop_or_default]
pub onmyclickevent:Callback<String>,
}

impl Component for EmitEventComponent {
type Message = Msg;
type Properties = Props;

fn create(props: Self::Properties, link: ComponentLink<Self>) -> Self {
Self {
link,
props: props.clone(),
name: props.name.into(),
show_message: false,
}
}

fn update(&mut self, msg: Self::Message) -> ShouldRender {
match msg {
Msg::Click() => self.show_message = true,
Msg::Click4Event() => self.props.onmyclickevent.emit("Hello Loise".into()),
}
true
}

fn change(&mut self, props: Self::Properties) -> ShouldRender {
if self.props != props {
self.props = props;
true
} else {
false
}
}

fn view(&self) -> Html {
if !self.show_message {
html! {
<>
<button onclick=self.link.callback( |_| Msg::Click() )>{"Click here!"}</button>
</>
}
} else {
html! {
<>
{"Click on clark to raised an event for the parent container ;-)"}
rlasjunies marked this conversation as resolved.
Show resolved Hide resolved
<h1 onclick=self.link.callback( |_| Msg::Click4Event()) >
{format!("Hello {}",self.name)}</h1>
</>
}
}
}
}
```

## Define the Event

Here we are defining a new event named `onmyclickevent` with a `String` as parameter.

```rust
# use yew::prelude::*;
#
# pub struct EmitEventComponent {
# link: ComponentLink<Self>,
# props: Props,
# name: String,
# show_message: bool,
# }
#
# pub enum Msg {
# Click(),
# Click4Event(),
# }

// ...
#[derive(Properties, Clone, PartialEq)]
pub struct Props{
#[prop_or("Clark by default".to_string())]
pub name: String,
#[prop_or_default]
pub onmyclickevent:Callback<String>,
}
// ...

# impl Component for EmitEventComponent {
# type Message = Msg;
# type Properties = Props;
#
# fn create(props: Self::Properties, link: ComponentLink<Self>) -> Self {
# Self {
# link,
# props: props.clone(),
# name: props.name.into(),
# show_message: false,
# }
# }
#
# fn update(&mut self, msg: Self::Message) -> ShouldRender {
# match msg {
# Msg::Click() => self.show_message = true,
# Msg::Click4Event() => self.props.onmyclickevent.emit("Hello Loise".into()),
# }
# true
# }
#
# fn change(&mut self, props: Self::Properties) -> ShouldRender {
# if self.props != props {
# self.props = props;
# true
# } else {
# false
# }
# }
#
# fn view(&self) -> Html {
# if !self.show_message {
# html! {
# <>
# <button onclick=self.link.callback( |_| Msg::Click() )>{"Click here!"}</button>
# </>
# }
# } else {
# html! {
# <>
# {"Click on clark to raised an event for the parent container ;-)"}
# <h1 onclick=self.link.callback( |_| Msg::Click4Event()) >
# {format!("Hello {}",self.name)}</h1>
# </>
# }
# }
# }
# }

```

## Emit the Event

The event are usually emitted in the `update()` method as effect of message

```rust
# use yew::prelude::*;
#
# pub struct EmitEventComponent {
# link: ComponentLink<Self>,
# props: Props,
# name: String,
# show_message: bool,
# }
#
# pub enum Msg {
# Click(),
# Click4Event(),
# }
#
# #[derive(Properties, Clone, PartialEq)]
# pub struct Props{
# #[prop_or("Clark by default".to_string())]
# pub name: String,
#
# #[prop_or_default]
# pub onmyclickevent:Callback<String>,
# }
#
# impl Component for EmitEventComponent {
# type Message = Msg;
# type Properties = Props;
#
# fn create(props: Self::Properties, link: ComponentLink<Self>) -> Self {
# Self {
# link,
# props: props.clone(),
# name: props.name.into(),
# show_message: false,
# }
# }
// ...
fn update(&mut self, msg: Self::Message) -> ShouldRender {
match msg {
Msg::Click() => self.show_message = true,
Msg::Click4Event() => self.props.onmyclickevent.emit("Hello Loise".into()),
}
true
}
// ...
# fn change(&mut self, props: Self::Properties) -> ShouldRender {
# if self.props != props {
# self.props = props;
# true
# } else {
# false
# }
# }
#
# fn view(&self) -> Html {
# if !self.show_message {
# html! {
# <>
# <button onclick=self.link.callback( |_| Msg::Click() )>{"Click here!"}</button>
# </>
# }
# } else {
# html! {
# <>
# {"Click on clark to raised an event for the parent container ;-)"}
# <h1 onclick=self.link.callback( |_| Msg::Click4Event()) >
# {format!("Hello {}",self.name)}</h1>
# </>
# }
# }
# }
# }
```

## Mandatory or optionally binded events

Like for properties you can define the events to be be mandatory or optionaly binded in the parent component.

This is defined providing or not attributes to the event definition.

```rust
# use yew::prelude::*;
#
# pub struct EmitEventComponent {
# link: ComponentLink<Self>,
# props: Props,
# name: String,
# show_message: bool,
# }
#
# pub enum Msg {
# Click(),
# Click4Event(),
# }
// ...
#[derive(Properties, Clone, PartialEq)]
pub struct Props{
#[prop_or("Clark by default".to_string())]
pub name: String,

pub on_i_am_mandatory_event:Callback<()>,

#[prop_or_default]
pub on_i_am_optional_event:Callback<()>,
}
// ...
# impl Component for EmitEventComponent {
# type Message = Msg;
# type Properties = Props;
#
# fn create(props: Self::Properties, link: ComponentLink<Self>) -> Self {
# Self {
# link,
# props: props.clone(),
# name: props.name.into(),
# show_message: false,
# }
# }
#
# fn update(&mut self, msg: Self::Message) -> ShouldRender {
# match msg {
# Msg::Click() => self.show_message = true,
# Msg::Click4Event() => self.props.on_i_am_mandatory_event.emit(()),
# }
# true
# }
#
# fn change(&mut self, props: Self::Properties) -> ShouldRender {
# if self.props != props {
# self.props = props;
# true
# } else {
# false
# }
# }
#
# fn view(&self) -> Html {
# if !self.show_message {
# html! {
# <>
# <button onclick=self.link.callback( |_| Msg::Click() )>{"Click here!"}</button>
# </>
# }
# } else {
# html! {
# <>
# {"Click on clark to raised an event for the parent container ;-)"}
# <h1 onclick=self.link.callback( |_| Msg::Click4Event()) >
# {format!("Hello {}",self.name)}</h1>
# </>
# }
# }
# }
# }

```

Like for the properties a compilatioin error will be raised in case you omitted to bind a mandatory event. The message could be something like:
rlasjunies marked this conversation as resolved.
Show resolved Hide resolved

> no method named `build` found for struct `components::comp4::PropsBuilder<...PropsBuilderStep_missing_required_prop_name>` in the current scope
> method not found in `...::PropsBuilder<...PropsBuilderStep_missing_required_prop_name>`rustc(E0599)
comp4.rs(14, 10): method `build` not found for this`