Add components interaction example (#951)

This add a small example of how to use agents in order to send
messages between components.
This commit is contained in:
Filippo Merli 2020-02-18 12:45:41 +01:00 committed by GitHub
parent a5e74e7d1d
commit b534a4c83a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 184 additions and 0 deletions

View File

@ -23,4 +23,5 @@ members = [
"timer",
"todomvc",
"two_apps",
"pub_sub",
]

View File

@ -0,0 +1,11 @@
[package]
name = "event_bus"
version = "0.1.0"
edition = "2018"
[dependencies]
log = "0.4"
web_logger = "0.1"
serde = { version = "1.0", features = ["derive"] }
yew = { path = "../.." }
stdweb = "0.4.20"

View File

@ -0,0 +1,3 @@
## Sender receiver example
Basic example that show how components that are not aware of each other can communicate
using an agent.

View File

@ -0,0 +1,48 @@
use serde::{Deserialize, Serialize};
use std::collections::HashSet;
use std::fmt::Debug;
use yew::worker::*;
#[derive(Serialize, Deserialize, Debug)]
pub enum Request {
EventBusMsg(String),
}
pub struct EventBus {
link: AgentLink<EventBus>,
subscribers: HashSet<HandlerId>,
}
impl Agent for EventBus {
type Reach = Context;
type Message = ();
type Input = Request;
type Output = String;
fn create(link: AgentLink<Self>) -> Self {
EventBus {
link,
subscribers: HashSet::new(),
}
}
fn update(&mut self, _: Self::Message) {}
fn handle_input(&mut self, msg: Self::Input, _: HandlerId) {
match msg {
Request::EventBusMsg(s) => {
for sub in self.subscribers.iter() {
self.link.respond(*sub, s.clone());
}
}
}
}
fn connected(&mut self, id: HandlerId) {
self.subscribers.insert(id);
}
fn disconnected(&mut self, id: HandlerId) {
self.subscribers.remove(&id);
}
}

View File

@ -0,0 +1,33 @@
#![recursion_limit = "128"]
mod event_bus;
mod subscriber;
mod producer;
use subscriber::Subsciber;
use producer::Producer;
use yew::{html, Component, ComponentLink, Html, ShouldRender};
pub struct Model {}
impl Component for Model {
type Message = ();
type Properties = ();
fn create(_: Self::Properties, _: ComponentLink<Self>) -> Self {
Model {}
}
fn update(&mut self, _: Self::Message) -> ShouldRender {
false
}
fn view(&self) -> Html {
html! {
<div>
<Producer />
<Subsciber />
</div>
}
}
}

View File

@ -0,0 +1,3 @@
fn main() {
yew::start_app::<event_bus::Model>();
}

View File

@ -0,0 +1,46 @@
use crate::event_bus::EventBus;
use yew::agent::Dispatched;
use yew::prelude::*;
use crate::event_bus::Request;
use yew::agent::Dispatcher;
pub struct Producer {
link: ComponentLink<Producer>,
event_bus: Dispatcher<EventBus>,
}
pub enum Msg {
Clicked,
}
impl Component for Producer {
type Message = Msg;
type Properties = ();
fn create(_: Self::Properties, link: ComponentLink<Self>) -> Self {
let event_bus = EventBus::dispatcher();
Producer { event_bus, link }
}
fn update(&mut self, msg: Self::Message) -> ShouldRender {
match msg {
Msg::Clicked => {
self.event_bus
.send(Request::EventBusMsg(format!("Message receieved")));
false
}
}
}
fn view(&self) -> Html {
html! {
<button
onclick=self.link.callback(|_| Msg::Clicked)
>
{"PUSH ME"}
</button>
}
}
}

View File

@ -0,0 +1,39 @@
use super::event_bus::EventBus;
use yew::agent::Bridged;
use yew::{html, Bridge, Component, ComponentLink, Html, ShouldRender};
pub enum Msg {
NewMessage(String),
}
pub struct Subsciber {
message: String,
_producer: Box<dyn Bridge<EventBus>>,
}
impl Component for Subsciber {
type Message = Msg;
type Properties = ();
fn create(_: Self::Properties, link: ComponentLink<Self>) -> Self {
let callback = link.callback(|s| Msg::NewMessage(s));
let _producer = EventBus::bridge(callback);
Subsciber {
message: format!("No message yet"),
_producer,
}
}
fn update(&mut self, msg: Self::Message) -> ShouldRender {
match msg {
Msg::NewMessage(s) => self.message = s,
}
true
}
fn view(&self) -> Html {
html! {
<h1>{self.message.clone()}</h1>
}
}
}