mirror of
https://github.com/yewstack/yew.git
synced 2025-12-08 21:26:25 +00:00
Add requirement for braces around most props (#1939)
* Limit the properties to literals and brace-enclosed expressions * Update examples with new syntax * Update packages/yew-macro/src/props/prop.rs Co-authored-by: Teymour Aldridge <42674621+teymour-aldridge@users.noreply.github.com> * Fix lints and strip braces around single expressions * Update docs with new prop syntax * Add some test cases for new syntax * Ensure all tests are passing * Clean up missed code * Update tests * Update reverted docs * Revert versioned docs * Fix optional attributes paragraph * Remove accidentally added files * Remove accidentally added french docs * Update packages/yew-macro/src/props/prop.rs Co-authored-by: mc1098 <m.cripps1@uni.brighton.ac.uk> * Fix forgotten braces and test cases * Revert i18n old docs * Revert translated docs * Remove suggested fix in favour of more succinct error message * Update errors after rebase * Remove files accidentally added while rebasing * Fix merge conflicts Co-authored-by: Teymour Aldridge <42674621+teymour-aldridge@users.noreply.github.com> Co-authored-by: mc1098 <m.cripps1@uni.brighton.ac.uk>
This commit is contained in:
parent
d89f1ccc5c
commit
4a14d0f0a4
@ -130,7 +130,7 @@ impl Boid {
|
||||
points.push_str(&format!("{:.2},{:.2} ", x, y));
|
||||
}
|
||||
|
||||
html! { <polygon points=points fill=color /> }
|
||||
html! { <polygon points={points} fill={color} /> }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -73,7 +73,7 @@ impl Component for Model {
|
||||
html! {
|
||||
<>
|
||||
<h1 class="title">{ "Boids" }</h1>
|
||||
<Simulation settings=settings.clone() generation=generation paused=paused />
|
||||
<Simulation settings={settings.clone()} generation={generation} paused={paused} />
|
||||
{ self.view_panel() }
|
||||
</>
|
||||
}
|
||||
@ -87,9 +87,9 @@ impl Model {
|
||||
<div class="panel">
|
||||
{ self.view_settings() }
|
||||
<div class="panel__buttons">
|
||||
<button onclick=link.callback(|_| Msg::TogglePause)>{ pause_text }</button>
|
||||
<button onclick=link.callback(|_| Msg::ResetSettings)>{ "Use Defaults" }</button>
|
||||
<button onclick=link.callback(|_| Msg::RestartSimulation)>{ "Restart" }</button>
|
||||
<button onclick={link.callback(|_| Msg::TogglePause)}>{ pause_text }</button>
|
||||
<button onclick={link.callback(|_| Msg::ResetSettings)}>{ "Use Defaults" }</button>
|
||||
<button onclick={link.callback(|_| Msg::RestartSimulation)}>{ "Restart" }</button>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@ -119,48 +119,48 @@ impl Model {
|
||||
<div class="settings">
|
||||
<Slider label="Number of Boids"
|
||||
min=1.0 max=600.0
|
||||
onchange=settings_callback!(link, settings; boids as usize)
|
||||
value=settings.boids as f64
|
||||
onchange={settings_callback!(link, settings; boids as usize)}
|
||||
value={settings.boids as f64}
|
||||
/>
|
||||
<Slider label="View Distance"
|
||||
max=500.0 step=10.0
|
||||
onchange=settings_callback!(link, settings; visible_range)
|
||||
value=settings.visible_range
|
||||
onchange={settings_callback!(link, settings; visible_range)}
|
||||
value={settings.visible_range}
|
||||
/>
|
||||
<Slider label="Spacing"
|
||||
max=100.0
|
||||
onchange=settings_callback!(link, settings; min_distance)
|
||||
value=settings.min_distance
|
||||
onchange={settings_callback!(link, settings; min_distance)}
|
||||
value={settings.min_distance}
|
||||
/>
|
||||
<Slider label="Max Speed"
|
||||
max=50.0
|
||||
onchange=settings_callback!(link, settings; max_speed)
|
||||
value=settings.max_speed
|
||||
onchange={settings_callback!(link, settings; max_speed)}
|
||||
value={settings.max_speed}
|
||||
/>
|
||||
<Slider label="Cohesion"
|
||||
max=0.5 percentage=true
|
||||
onchange=settings_callback!(link, settings; cohesion_factor)
|
||||
value=settings.cohesion_factor
|
||||
onchange={settings_callback!(link, settings; cohesion_factor)}
|
||||
value={settings.cohesion_factor}
|
||||
/>
|
||||
<Slider label="Separation"
|
||||
max=1.0 percentage=true
|
||||
onchange=settings_callback!(link, settings; separation_factor)
|
||||
value=settings.separation_factor
|
||||
onchange={settings_callback!(link, settings; separation_factor)}
|
||||
value={settings.separation_factor}
|
||||
/>
|
||||
<Slider label="Alignment"
|
||||
max=0.5 percentage=true
|
||||
onchange=settings_callback!(link, settings; alignment_factor)
|
||||
value=settings.alignment_factor
|
||||
onchange={settings_callback!(link, settings; alignment_factor)}
|
||||
value={settings.alignment_factor}
|
||||
/>
|
||||
<Slider label="Turn Speed"
|
||||
max=1.5 percentage=true
|
||||
onchange=settings_callback!(link, settings; turn_speed_ratio)
|
||||
value=settings.turn_speed_ratio
|
||||
onchange={settings_callback!(link, settings; turn_speed_ratio)}
|
||||
value={settings.turn_speed_ratio}
|
||||
/>
|
||||
<Slider label="Color Adaption"
|
||||
max=1.5 percentage=true
|
||||
onchange=settings_callback!(link, settings; color_adapt_factor)
|
||||
value=settings.color_adapt_factor
|
||||
onchange={settings_callback!(link, settings; color_adapt_factor)}
|
||||
value={settings.color_adapt_factor}
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
|
||||
@ -104,7 +104,7 @@ impl Component for Simulation {
|
||||
let view_box = format!("0 0 {} {}", SIZE.x, SIZE.y);
|
||||
|
||||
html! {
|
||||
<svg class="simulation-window" viewBox=view_box>
|
||||
<svg class="simulation-window" viewBox={view_box}>
|
||||
{ for self.boids.iter().map(Boid::render) }
|
||||
</svg>
|
||||
}
|
||||
|
||||
@ -80,13 +80,13 @@ impl Component for Slider {
|
||||
|
||||
html! {
|
||||
<div class="slider">
|
||||
<label for=id.clone() class="slider__label">{ label }</label>
|
||||
<label for={id.clone()} class="slider__label">{ label }</label>
|
||||
<input type="range"
|
||||
id=id
|
||||
id={id}
|
||||
class="slider__input"
|
||||
min=min.to_string() max=max.to_string() step=step.to_string()
|
||||
oninput=onchange.reform(|data: InputData| data.value.parse().unwrap())
|
||||
value=value.to_string()
|
||||
min={min.to_string()} max={max.to_string()} step={step.to_string()}
|
||||
oninput={onchange.reform(|data: InputData| data.value.parse().unwrap())}
|
||||
value={value.to_string()}
|
||||
/>
|
||||
<span class="slider__value">{ display_value }</span>
|
||||
</div>
|
||||
|
||||
@ -45,17 +45,17 @@ impl Component for Model {
|
||||
<div>
|
||||
<div class="panel">
|
||||
// A button to send the Increment message
|
||||
<button class="button" onclick=self.link.callback(|_| Msg::Increment)>
|
||||
<button class="button" onclick={self.link.callback(|_| Msg::Increment)}>
|
||||
{ "+1" }
|
||||
</button>
|
||||
|
||||
// A button to send the Decrement message
|
||||
<button onclick=self.link.callback(|_| Msg::Decrement)>
|
||||
<button onclick={self.link.callback(|_| Msg::Decrement)}>
|
||||
{ "-1" }
|
||||
</button>
|
||||
|
||||
// A button to send two Increment messages
|
||||
<button onclick=self.link.batch_callback(|_| vec![Msg::Increment, Msg::Increment])>
|
||||
<button onclick={self.link.batch_callback(|_| vec![Msg::Increment, Msg::Increment])}>
|
||||
{ "+1, +1" }
|
||||
</button>
|
||||
|
||||
|
||||
@ -76,32 +76,32 @@ impl Component for AddClientForm {
|
||||
<>
|
||||
<div class="names">
|
||||
<input
|
||||
class=classes!("new-client", "firstname")
|
||||
class={classes!("new-client", "firstname")}
|
||||
placeholder="First name"
|
||||
value=client.first_name.clone()
|
||||
oninput=link.callback(|e: InputData| Msg::UpdateFirstName(e.value))
|
||||
value={client.first_name.clone()}
|
||||
oninput={link.callback(|e: InputData| Msg::UpdateFirstName(e.value))}
|
||||
/>
|
||||
<input
|
||||
class=classes!("new-client", "lastname")
|
||||
class={classes!("new-client", "lastname")}
|
||||
placeholder="Last name"
|
||||
value=client.last_name.clone()
|
||||
oninput=link.callback(|e: InputData| Msg::UpdateLastName(e.value))
|
||||
value={client.last_name.clone()}
|
||||
oninput={link.callback(|e: InputData| Msg::UpdateLastName(e.value))}
|
||||
/>
|
||||
<textarea
|
||||
class=classes!("new-client", "description")
|
||||
class={classes!("new-client", "description")}
|
||||
placeholder="Description"
|
||||
value=client.description.clone()
|
||||
oninput=link.callback(|e: InputData| Msg::UpdateDescription(e.value))
|
||||
value={client.description.clone()}
|
||||
oninput={link.callback(|e: InputData| Msg::UpdateDescription(e.value))}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<button
|
||||
disabled=client.first_name.is_empty() || client.last_name.is_empty()
|
||||
onclick=link.callback(|_| Msg::Add)
|
||||
disabled={client.first_name.is_empty() || client.last_name.is_empty()}
|
||||
onclick={link.callback(|_| Msg::Add)}
|
||||
>
|
||||
{ "Add New" }
|
||||
</button>
|
||||
<button onclick=link.callback(|_| Msg::Abort)>
|
||||
<button onclick={link.callback(|_| Msg::Abort)}>
|
||||
{ "Go Back" }
|
||||
</button>
|
||||
</>
|
||||
|
||||
@ -97,21 +97,21 @@ impl Component for Model {
|
||||
<div class="clients">
|
||||
{ for self.clients.iter().map(Client::render) }
|
||||
</div>
|
||||
<button onclick=self.link.callback(|_| Msg::SwitchTo(Scene::NewClientForm))>{ "Add New" }</button>
|
||||
<button onclick=self.link.callback(|_| Msg::SwitchTo(Scene::Settings))>{ "Settings" }</button>
|
||||
<button onclick={self.link.callback(|_| Msg::SwitchTo(Scene::NewClientForm))}>{ "Add New" }</button>
|
||||
<button onclick={self.link.callback(|_| Msg::SwitchTo(Scene::Settings))}>{ "Settings" }</button>
|
||||
</div>
|
||||
},
|
||||
Scene::NewClientForm => html! {
|
||||
<div class="crm">
|
||||
<h1>{"Add a new client"}</h1>
|
||||
<AddClientForm on_add=self.link.callback(Msg::AddClient) on_abort=self.link.callback(|_| Msg::SwitchTo(Scene::ClientsList)) />
|
||||
<AddClientForm on_add={self.link.callback(Msg::AddClient)} on_abort={self.link.callback(|_| Msg::SwitchTo(Scene::ClientsList))} />
|
||||
</div>
|
||||
},
|
||||
Scene::Settings => html! {
|
||||
<div>
|
||||
<h1>{"Settings"}</h1>
|
||||
<button onclick=self.link.callback(|_| Msg::ClearClients)>{ "Remove all clients" }</button>
|
||||
<button onclick=self.link.callback(|_| Msg::SwitchTo(Scene::ClientsList))>{ "Go Back" }</button>
|
||||
<button onclick={self.link.callback(|_| Msg::ClearClients)}>{ "Remove all clients" }</button>
|
||||
<button onclick={self.link.callback(|_| Msg::SwitchTo(Scene::ClientsList))}>{ "Go Back" }</button>
|
||||
</div>
|
||||
},
|
||||
}
|
||||
|
||||
@ -58,7 +58,7 @@ impl Component for CounterModel {
|
||||
</p>
|
||||
|
||||
// Add button to send a destroy command to the parent app
|
||||
<button class="destroy" onclick=Callback::from(move |_| destroy_callback.emit(()))>
|
||||
<button class="destroy" onclick={Callback::from(move |_| destroy_callback.emit(()))}>
|
||||
{ "Destroy this app" }
|
||||
</button>
|
||||
</>
|
||||
|
||||
@ -98,13 +98,13 @@ impl Component for Model {
|
||||
// Create button to create a new app
|
||||
<button
|
||||
class="create"
|
||||
onclick=self.link.callback(|_| Msg::SpawnCounterAppInstance)
|
||||
onclick={self.link.callback(|_| Msg::SpawnCounterAppInstance)}
|
||||
>
|
||||
{ "Spawn new CounterModel app" }
|
||||
</button>
|
||||
</div>
|
||||
// Create a container for all the app instances
|
||||
<div ref=self.apps_container_ref.clone()>
|
||||
<div ref={self.apps_container_ref.clone()}>
|
||||
</div>
|
||||
</>
|
||||
}
|
||||
|
||||
@ -87,7 +87,7 @@ impl Component for Model {
|
||||
<div>
|
||||
<div>
|
||||
<p>{ "Choose a file to upload to see the uploaded bytes" }</p>
|
||||
<input type="file" multiple=true onchange=self.link.callback(move |value| {
|
||||
<input type="file" multiple=true onchange={self.link.callback(move |value| {
|
||||
let mut result = Vec::new();
|
||||
if let ChangeData::Files(files) = value {
|
||||
let files = js_sys::try_iter(&files)
|
||||
@ -98,12 +98,12 @@ impl Component for Model {
|
||||
result.extend(files);
|
||||
}
|
||||
Msg::Files(result, flag)
|
||||
})
|
||||
})}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label>{ "Read bytes" }</label>
|
||||
<input type="checkbox" checked=flag onclick=self.link.callback(|_| Msg::ToggleReadBytes) />
|
||||
<input type="checkbox" checked={flag} onclick={self.link.callback(|_| Msg::ToggleReadBytes)} />
|
||||
</div>
|
||||
<ul>
|
||||
{ for self.files.iter().map(|f| Self::view_file(f)) }
|
||||
|
||||
@ -118,10 +118,10 @@ impl Component for Model {
|
||||
match &self.markdown {
|
||||
FetchState::NotFetching => html! {
|
||||
<>
|
||||
<button onclick=self.link.callback(|_| Msg::GetMarkdown)>
|
||||
<button onclick={self.link.callback(|_| Msg::GetMarkdown)}>
|
||||
{ "Get Markdown" }
|
||||
</button>
|
||||
<button onclick=self.link.callback(|_| Msg::GetError)>
|
||||
<button onclick={self.link.callback(|_| Msg::GetError)}>
|
||||
{ "Get using incorrect URL" }
|
||||
</button>
|
||||
</>
|
||||
|
||||
@ -95,8 +95,8 @@ impl Model {
|
||||
}
|
||||
};
|
||||
html! {
|
||||
<div key=idx class=classes!("game-cellule", cellule_status)
|
||||
onclick=self.link.callback(move |_| Msg::ToggleCellule(idx))>
|
||||
<div key={idx} class={classes!("game-cellule", cellule_status)}
|
||||
onclick={self.link.callback(move |_| Msg::ToggleCellule(idx))}>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
@ -180,7 +180,7 @@ impl Component for Model {
|
||||
.enumerate()
|
||||
.map(|(x, cell)| self.view_cellule(idx_offset + x, cell));
|
||||
html! {
|
||||
<div key=y class="game-row">
|
||||
<div key={y} class="game-row">
|
||||
{ for cells }
|
||||
</div>
|
||||
}
|
||||
@ -198,11 +198,11 @@ impl Component for Model {
|
||||
{ for cell_rows }
|
||||
</div>
|
||||
<div class="game-buttons">
|
||||
<button class="game-button" onclick=self.link.callback(|_| Msg::Random)>{ "Random" }</button>
|
||||
<button class="game-button" onclick=self.link.callback(|_| Msg::Step)>{ "Step" }</button>
|
||||
<button class="game-button" onclick=self.link.callback(|_| Msg::Start)>{ "Start" }</button>
|
||||
<button class="game-button" onclick=self.link.callback(|_| Msg::Stop)>{ "Stop" }</button>
|
||||
<button class="game-button" onclick=self.link.callback(|_| Msg::Reset)>{ "Reset" }</button>
|
||||
<button class="game-button" onclick={self.link.callback(|_| Msg::Random)}>{ "Random" }</button>
|
||||
<button class="game-button" onclick={self.link.callback(|_| Msg::Step)}>{ "Step" }</button>
|
||||
<button class="game-button" onclick={self.link.callback(|_| Msg::Start)}>{ "Start" }</button>
|
||||
<button class="game-button" onclick={self.link.callback(|_| Msg::Stop)}>{ "Stop" }</button>
|
||||
<button class="game-button" onclick={self.link.callback(|_| Msg::Reset)}>{ "Reset" }</button>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
@ -57,13 +57,13 @@ impl Component for Model {
|
||||
<>
|
||||
<textarea
|
||||
class="code-block"
|
||||
oninput=self.link.callback(|input: InputData| Msg::Payload(input.value))
|
||||
value=self.payload.clone()
|
||||
oninput={self.link.callback(|input: InputData| Msg::Payload(input.value))}
|
||||
value={self.payload.clone()}
|
||||
/>
|
||||
<button onclick=self.link.callback(|_| Msg::Payload(bindings::get_payload()))>
|
||||
<button onclick={self.link.callback(|_| Msg::Payload(bindings::get_payload()))}>
|
||||
{ "Get the payload!" }
|
||||
</button>
|
||||
<button onclick=self.link.callback(|_| Msg::AsyncPayload) >
|
||||
<button onclick={self.link.callback(|_| Msg::AsyncPayload)} >
|
||||
{ "Get the payload later!" }
|
||||
</button>
|
||||
<p class="code-block">
|
||||
|
||||
@ -147,7 +147,7 @@ impl Component for Model {
|
||||
html! {
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<p class="h2" ref=self.delta_ref.clone()/>
|
||||
<p class="h2" ref={self.delta_ref.clone()}/>
|
||||
<hr />
|
||||
</div>
|
||||
{ self.action_view() }
|
||||
@ -169,8 +169,8 @@ impl Model {
|
||||
{ self.build_component_ratio }
|
||||
</p>
|
||||
<input name="ratio" type="range" class="form-control-range" min="0.0" max="1.0" step="any"
|
||||
value=self.build_component_ratio.to_string()
|
||||
oninput=self.link.callback(|e: InputData| Msg::ChangeRatio(e.value))
|
||||
value={self.build_component_ratio.to_string()}
|
||||
oninput={self.link.callback(|e: InputData| Msg::ChangeRatio(e.value))}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -182,74 +182,74 @@ impl Model {
|
||||
<>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<button class="btn_size alert alert-danger" onclick=self.link.callback(|_| Msg::DeleteEverybody)>
|
||||
<button class="btn_size alert alert-danger" onclick={self.link.callback(|_| Msg::DeleteEverybody)}>
|
||||
{ "Delete everybody" }
|
||||
</button>
|
||||
</div>
|
||||
<div class="col">
|
||||
<button class="btn_size alert alert-success" onclick=self.link.callback(|_| Msg::CreatePersons(1))>
|
||||
<button class="btn_size alert alert-success" onclick={self.link.callback(|_| Msg::CreatePersons(1))}>
|
||||
{ "Create 1" }
|
||||
</button>
|
||||
</div>
|
||||
<div class="col">
|
||||
<button class="btn_size alert alert-success" onclick=self.link.callback(|_| Msg::CreatePersons(5))>
|
||||
<button class="btn_size alert alert-success" onclick={self.link.callback(|_| Msg::CreatePersons(5))}>
|
||||
{ "Create 5" }
|
||||
</button>
|
||||
</div>
|
||||
<div class="col">
|
||||
<button class="btn_size alert alert-success" onclick=self.link.callback(|_| Msg::CreatePersons(100))>
|
||||
<button class="btn_size alert alert-success" onclick={self.link.callback(|_| Msg::CreatePersons(100))}>
|
||||
{ "Create 100" }
|
||||
</button>
|
||||
</div>
|
||||
<div class="col">
|
||||
<button class="btn_size alert alert-success" onclick=self.link.callback(|_| Msg::CreatePersons(500))>
|
||||
<button class="btn_size alert alert-success" onclick={self.link.callback(|_| Msg::CreatePersons(500))}>
|
||||
{ "Create 500" }
|
||||
</button>
|
||||
</div>
|
||||
<div class="col">
|
||||
<button class="btn_size alert alert-success" onclick=self.link.callback(|_| Msg::CreatePersonsPrepend(1))>
|
||||
<button class="btn_size alert alert-success" onclick={self.link.callback(|_| Msg::CreatePersonsPrepend(1))}>
|
||||
{ "Prepend 1" }
|
||||
</button>
|
||||
</div>
|
||||
<div class="col">
|
||||
<button class="btn_size alert alert-success" onclick=self.link.callback(|_| Msg::CreatePersonsPrepend(5))>
|
||||
<button class="btn_size alert alert-success" onclick={self.link.callback(|_| Msg::CreatePersonsPrepend(5))}>
|
||||
{ "Prepend 5" }
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<button class="btn_size alert alert-warning" onclick=self.link.callback(|_| Msg::ToggleKeyed)>
|
||||
<button class="btn_size alert alert-warning" onclick={self.link.callback(|_| Msg::ToggleKeyed)}>
|
||||
{ if self.keyed { "Disable keys" } else { "Enable keys" } }
|
||||
</button>
|
||||
</div>
|
||||
<div class="col">
|
||||
<button class="btn_size alert alert-info" onclick=self.link.callback(|_| Msg::SwapRandom)>
|
||||
<button class="btn_size alert alert-info" onclick={self.link.callback(|_| Msg::SwapRandom)}>
|
||||
{ "Swap random" }
|
||||
</button>
|
||||
</div>
|
||||
<div class="col">
|
||||
<button class="btn_size alert alert-info" onclick=self.link.callback(|_| Msg::ReverseList)>
|
||||
<button class="btn_size alert alert-info" onclick={self.link.callback(|_| Msg::ReverseList)}>
|
||||
{ "Reverse list" }
|
||||
</button>
|
||||
</div>
|
||||
<div class="col">
|
||||
<button class="btn_size alert alert-info" onclick=self.link.callback(|_| Msg::SortById)>
|
||||
<button class="btn_size alert alert-info" onclick={self.link.callback(|_| Msg::SortById)}>
|
||||
{ "Sort by id" }
|
||||
</button>
|
||||
</div>
|
||||
<div class="col">
|
||||
<button class="btn_size alert alert-info" onclick=self.link.callback(|_| Msg::SortByName)>
|
||||
<button class="btn_size alert alert-info" onclick={self.link.callback(|_| Msg::SortByName)}>
|
||||
{ "Sort by name" }
|
||||
</button>
|
||||
</div>
|
||||
<div class="col">
|
||||
<button class="btn_size alert alert-info" onclick=self.link.callback(|_| Msg::SortByAge)>
|
||||
<button class="btn_size alert alert-info" onclick={self.link.callback(|_| Msg::SortByAge)}>
|
||||
{ "Sort by age" }
|
||||
</button>
|
||||
</div>
|
||||
<div class="col">
|
||||
<button class="btn_size alert alert-info" onclick=self.link.callback(|_| Msg::SortByAddress)>
|
||||
<button class="btn_size alert alert-info" onclick={self.link.callback(|_| Msg::SortByAddress)}>
|
||||
{ "Sort by address" }
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@ -69,7 +69,7 @@ impl Component for PersonComponent {
|
||||
|
||||
fn view(&self) -> Html {
|
||||
html! {
|
||||
<div class="text-info" id=self.info.id.to_string()>
|
||||
<div class="text-info" id={self.info.id.to_string()}>
|
||||
{ self.info.render() }
|
||||
</div>
|
||||
}
|
||||
@ -102,13 +102,13 @@ impl PersonType {
|
||||
Self::Inline(info) => {
|
||||
if keyed {
|
||||
html! {
|
||||
<div key=info.id.to_string() class="text-danger" id=info.id.to_string()>
|
||||
<div key={info.id.to_string()} class="text-danger" id={info.id.to_string()}>
|
||||
{ info.render() }
|
||||
</div>
|
||||
}
|
||||
} else {
|
||||
html! {
|
||||
<div class="text-danger" id=info.id.to_string()>
|
||||
<div class="text-danger" id={info.id.to_string()}>
|
||||
{ info.render() }
|
||||
</div>
|
||||
}
|
||||
@ -116,9 +116,9 @@ impl PersonType {
|
||||
}
|
||||
Self::Component(info) => {
|
||||
if keyed {
|
||||
html! { <PersonComponent key=info.id.to_string() info=info.clone() /> }
|
||||
html! { <PersonComponent key={info.id.to_string()} info={info.clone()} /> }
|
||||
} else {
|
||||
html! { <PersonComponent info=info.clone() /> }
|
||||
html! { <PersonComponent info={info.clone()} /> }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -39,8 +39,8 @@ impl Component for Model {
|
||||
html! {
|
||||
<div>
|
||||
<input
|
||||
value=self.name.clone()
|
||||
oninput=self.link.callback(|e: InputData| Msg::UpdateName(e.value))
|
||||
value={self.name.clone()}
|
||||
oninput={self.link.callback(|e: InputData| Msg::UpdateName(e.value))}
|
||||
/>
|
||||
<p>{ self.name.chars().rev().collect::<String>() }</p>
|
||||
</div>
|
||||
|
||||
@ -76,9 +76,9 @@ impl Component for Model {
|
||||
html! {
|
||||
<div>
|
||||
<nav class="menu">
|
||||
<button onclick=self.link.callback(|_| Msg::SendToWorker)>{ "Send to Thread" }</button>
|
||||
<button onclick=self.link.callback(|_| Msg::SendToJob)>{ "Send to Job" }</button>
|
||||
<button onclick=self.link.callback(|_| Msg::SendToContext)>{ "Send to Context" }</button>
|
||||
<button onclick={self.link.callback(|_| Msg::SendToWorker)}>{ "Send to Thread" }</button>
|
||||
<button onclick={self.link.callback(|_| Msg::SendToJob)}>{ "Send to Job" }</button>
|
||||
<button onclick={self.link.callback(|_| Msg::SendToContext)}>{ "Send to Context" }</button>
|
||||
</nav>
|
||||
</div>
|
||||
}
|
||||
|
||||
@ -48,21 +48,22 @@ impl Component for App {
|
||||
let sub_list_link = &self.sub_list_link;
|
||||
|
||||
// note the use of `html_nested!` instead of `html!`.
|
||||
let letters = ('A'..='C')
|
||||
.map(|letter| html_nested! { <ListItem name=letter.to_string() on_hover=on_hover /> });
|
||||
let letters = ('A'..='C').map(
|
||||
|letter| html_nested! { <ListItem name={letter.to_string()} on_hover={on_hover} /> },
|
||||
);
|
||||
|
||||
html! {
|
||||
<div class="main" onmouseenter=onmouseenter>
|
||||
<div class="main" onmouseenter={onmouseenter}>
|
||||
<h1>{ "Nested List Demo" }</h1>
|
||||
<List on_hover=on_hover weak_link=list_link>
|
||||
<ListHeader text="Calling all Rusties!" on_hover=on_hover list_link=list_link />
|
||||
<ListItem name="Rustin" on_hover=on_hover />
|
||||
<ListItem hide=true name="Rustaroo" on_hover=on_hover />
|
||||
<ListItem name="Rustifer" on_hover=on_hover>
|
||||
<List on_hover={on_hover} weak_link={list_link}>
|
||||
<ListHeader text="Calling all Rusties!" on_hover={on_hover} list_link={list_link} />
|
||||
<ListItem name="Rustin" on_hover={on_hover} />
|
||||
<ListItem hide=true name="Rustaroo" on_hover={on_hover} />
|
||||
<ListItem name="Rustifer" on_hover={on_hover}>
|
||||
<div class="sublist">{ "Sublist!" }</div>
|
||||
<List on_hover=on_hover weak_link=sub_list_link>
|
||||
<ListHeader text="Sub Rusties!" on_hover=on_hover list_link=sub_list_link/>
|
||||
<ListItem hide=true name="Hidden Sub" on_hover=on_hover />
|
||||
<List on_hover={on_hover} weak_link={sub_list_link}>
|
||||
<ListHeader text="Sub Rusties!" on_hover={on_hover} list_link={sub_list_link}/>
|
||||
<ListItem hide=true name="Hidden Sub" on_hover={on_hover} />
|
||||
{ for letters }
|
||||
</List>
|
||||
</ListItem>
|
||||
|
||||
@ -44,8 +44,8 @@ impl Component for ListHeader {
|
||||
html! {
|
||||
<div
|
||||
class="list-header"
|
||||
onmouseover=onmouseover
|
||||
onclick=list_link.callback(|_| ListMsg::HeaderClick)
|
||||
onmouseover={onmouseover}
|
||||
onclick={list_link.callback(|_| ListMsg::HeaderClick)}
|
||||
>
|
||||
{ &self.props.text }
|
||||
</div>
|
||||
|
||||
@ -45,7 +45,7 @@ impl Component for ListItem {
|
||||
})
|
||||
};
|
||||
html! {
|
||||
<div class="list-item" onmouseover=onmouseover>
|
||||
<div class="list-item" onmouseover={onmouseover}>
|
||||
{ &self.props.name }
|
||||
{ self.view_details() }
|
||||
</div>
|
||||
|
||||
@ -102,8 +102,8 @@ impl Component for List {
|
||||
let onmouseover = self.props.on_hover.reform(|_| Hovered::List);
|
||||
let onmouseout = self.props.on_hover.reform(|_| Hovered::None);
|
||||
html! {
|
||||
<div class="list-container" onmouseout=onmouseout onmouseover=onmouseover>
|
||||
<div class=classes!("list", inactive)>
|
||||
<div class="list-container" onmouseout={onmouseout} onmouseover={onmouseover}>
|
||||
<div class={classes!("list", inactive)}>
|
||||
{ self.view_header() }
|
||||
<div class="items">
|
||||
{ self.view_items() }
|
||||
|
||||
@ -41,7 +41,7 @@ impl Component for InputComponent {
|
||||
<input
|
||||
type="text"
|
||||
class="input-component"
|
||||
onmouseover=self.link.callback(|_| Msg::Hover)
|
||||
onmouseover={self.link.callback(|_| Msg::Hover)}
|
||||
/>
|
||||
}
|
||||
}
|
||||
|
||||
@ -65,16 +65,16 @@ impl Component for Model {
|
||||
<label>{ "Using tag ref: " }</label>
|
||||
<input
|
||||
type="text"
|
||||
ref=self.refs[0].clone()
|
||||
ref={self.refs[0].clone()}
|
||||
class="input-element"
|
||||
onmouseover=self.link.callback(|_| Msg::HoverIndex(0))
|
||||
onmouseover={self.link.callback(|_| Msg::HoverIndex(0))}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label>{ "Using component ref: " }</label>
|
||||
<InputComponent
|
||||
ref=self.refs[1].clone()
|
||||
on_hover=self.link.callback(|_| Msg::HoverIndex(1))
|
||||
ref={self.refs[1].clone()}
|
||||
on_hover={self.link.callback(|_| Msg::HoverIndex(1))}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -38,7 +38,7 @@ impl Component for Producer {
|
||||
|
||||
fn view(&self) -> Html {
|
||||
html! {
|
||||
<button onclick=self.link.callback(|_| Msg::Clicked)>
|
||||
<button onclick={self.link.callback(|_| Msg::Clicked)}>
|
||||
{ "PRESS ME" }
|
||||
</button>
|
||||
}
|
||||
|
||||
@ -41,7 +41,7 @@ impl Component for AuthorCard {
|
||||
<div class="media">
|
||||
<div class="media-left">
|
||||
<figure class="image is-128x128">
|
||||
<img src=author.image_url.clone() />
|
||||
<img src={author.image_url.clone()} />
|
||||
</figure>
|
||||
</div>
|
||||
<div class="media-content">
|
||||
@ -54,7 +54,7 @@ impl Component for AuthorCard {
|
||||
</div>
|
||||
</div>
|
||||
<footer class="card-footer">
|
||||
<Link<Route> classes=classes!("card-footer-item") route=Route::Author { id: author.seed }>
|
||||
<Link<Route> classes={classes!("card-footer-item")} route={Route::Author { id: author.seed }}>
|
||||
{ "Profile" }
|
||||
</Link<Route>>
|
||||
</footer>
|
||||
|
||||
@ -53,7 +53,7 @@ impl Pagination {
|
||||
|
||||
html! {
|
||||
<li>
|
||||
<a class=classes!("pagination-link", is_current_class) aria-label=format!("Goto page {}", to_page) onclick=onclick>
|
||||
<a class={classes!("pagination-link", is_current_class)} aria-label={format!("Goto page {}", to_page)} onclick={onclick}>
|
||||
{ to_page }
|
||||
</a>
|
||||
</li>
|
||||
@ -114,14 +114,14 @@ impl Pagination {
|
||||
html! {
|
||||
<>
|
||||
<a class="pagination-previous"
|
||||
disabled=page==1
|
||||
onclick=on_switch_page.reform(move |_| page - 1)
|
||||
disabled={page==1}
|
||||
onclick={on_switch_page.reform(move |_| page - 1)}
|
||||
>
|
||||
{ "Previous" }
|
||||
</a>
|
||||
<a class="pagination-next"
|
||||
disabled=page==total_pages
|
||||
onclick=on_switch_page.reform(move |_| page + 1)
|
||||
disabled={page==total_pages}
|
||||
onclick={on_switch_page.reform(move |_| page + 1)}
|
||||
>
|
||||
{ "Next page" }
|
||||
</a>
|
||||
|
||||
@ -39,14 +39,14 @@ impl Component for PostCard {
|
||||
<div class="card">
|
||||
<div class="card-image">
|
||||
<figure class="image is-2by1">
|
||||
<img src=post.image_url.clone() loading="lazy" />
|
||||
<img src={post.image_url.clone()} loading="lazy" />
|
||||
</figure>
|
||||
</div>
|
||||
<div class="card-content">
|
||||
<Link<Route> classes=classes!("title", "is-block") route=Route::Post { id: post.seed }>
|
||||
<Link<Route> classes={classes!("title", "is-block")} route={Route::Post { id: post.seed }}>
|
||||
{ &post.title }
|
||||
</Link<Route>>
|
||||
<Link<Route> classes=classes!("subtitle", "is-block") route=Route::Author { id: post.author.seed }>
|
||||
<Link<Route> classes={classes!("subtitle", "is-block")} route={Route::Author { id: post.author.seed }}>
|
||||
{ &post.author.name }
|
||||
</Link<Route>>
|
||||
</div>
|
||||
|
||||
@ -64,7 +64,7 @@ impl Component for ProgressDelay {
|
||||
fn view(&self) -> Html {
|
||||
let value = self.value;
|
||||
html! {
|
||||
<progress class="progress is-primary" value=value.to_string() max=1.0>
|
||||
<progress class="progress is-primary" value={value.to_string()} max=1.0>
|
||||
{ format!("{:.0}%", 100.0 * value) }
|
||||
</progress>
|
||||
}
|
||||
|
||||
@ -65,7 +65,7 @@ impl Component for Model {
|
||||
{ self.view_nav() }
|
||||
|
||||
<main>
|
||||
<Router<Route> render=Router::render(switch) />
|
||||
<Router<Route> render={Router::render(switch)} />
|
||||
</main>
|
||||
<footer class="footer">
|
||||
<div class="content has-text-centered">
|
||||
@ -97,21 +97,21 @@ impl Model {
|
||||
<h1 class="navbar-item is-size-3">{ "Yew Blog" }</h1>
|
||||
|
||||
<a role="button"
|
||||
class=classes!("navbar-burger", "burger", active_class)
|
||||
class={classes!("navbar-burger", "burger", active_class)}
|
||||
aria-label="menu" aria-expanded="false"
|
||||
onclick=link.callback(|_| Msg::ToggleNavbar)
|
||||
onclick={link.callback(|_| Msg::ToggleNavbar)}
|
||||
>
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
</a>
|
||||
</div>
|
||||
<div class=classes!("navbar-menu", active_class)>
|
||||
<div class={classes!("navbar-menu", active_class)}>
|
||||
<div class="navbar-start">
|
||||
<Link<Route> classes=classes!("navbar-item") route=Route::Home>
|
||||
<Link<Route> classes={classes!("navbar-item")} route={Route::Home}>
|
||||
{ "Home" }
|
||||
</Link<Route>>
|
||||
<Link<Route> classes=classes!("navbar-item") route=Route::Posts>
|
||||
<Link<Route> classes={classes!("navbar-item")} route={Route::Posts}>
|
||||
{ "Posts" }
|
||||
</Link<Route>>
|
||||
|
||||
@ -121,7 +121,7 @@ impl Model {
|
||||
</a>
|
||||
<div class="navbar-dropdown">
|
||||
<a class="navbar-item">
|
||||
<Link<Route> classes=classes!("navbar-item") route=Route::Authors>
|
||||
<Link<Route> classes={classes!("navbar-item")} route={Route::Authors}>
|
||||
{ "Meet the authors" }
|
||||
</Link<Route>>
|
||||
</a>
|
||||
@ -137,13 +137,13 @@ impl Model {
|
||||
fn switch(routes: &Route) -> Html {
|
||||
match routes {
|
||||
Route::Post { id } => {
|
||||
html! { <Post seed=*id /> }
|
||||
html! { <Post seed={*id} /> }
|
||||
}
|
||||
Route::Posts => {
|
||||
html! { <PostList /> }
|
||||
}
|
||||
Route::Author { id } => {
|
||||
html! { <Author seed=*id /> }
|
||||
html! { <Author seed={*id} /> }
|
||||
}
|
||||
Route::Authors => {
|
||||
html! { <AuthorList /> }
|
||||
|
||||
@ -54,7 +54,7 @@ impl Component for Author {
|
||||
</div>
|
||||
<div class="tile is-parent">
|
||||
<figure class="tile is-child image is-square">
|
||||
<img src=author.image_url.clone() />
|
||||
<img src={author.image_url.clone()} />
|
||||
</figure>
|
||||
</div>
|
||||
<div class="tile is-parent">
|
||||
|
||||
@ -42,7 +42,7 @@ impl Component for AuthorList {
|
||||
html! {
|
||||
<div class="tile is-parent">
|
||||
<div class="tile is-child">
|
||||
<AuthorCard seed=seed />
|
||||
<AuthorCard seed={seed} />
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@ -71,7 +71,7 @@ impl Component for AuthorList {
|
||||
<div class="tile is-ancestor">
|
||||
{ for authors }
|
||||
</div>
|
||||
<ProgressDelay duration_ms=CAROUSEL_DELAY_MS on_complete=self.link.callback(|_| Msg::NextAuthors) />
|
||||
<ProgressDelay duration_ms={CAROUSEL_DELAY_MS} on_complete={self.link.callback(|_| Msg::NextAuthors)} />
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@ -47,7 +47,7 @@ impl Component for Post {
|
||||
html! {
|
||||
<>
|
||||
<section class="hero is-medium is-light has-background">
|
||||
<img class="hero-background is-transparent" src=Cow::Owned(post.meta.image_url.clone()) />
|
||||
<img class="hero-background is-transparent" src={Cow::Owned(post.meta.image_url.clone())} />
|
||||
<div class="hero-body">
|
||||
<div class="container">
|
||||
<h1 class="title">
|
||||
@ -55,7 +55,7 @@ impl Component for Post {
|
||||
</h1>
|
||||
<h2 class="subtitle">
|
||||
{ "by " }
|
||||
<Link<Route> classes=classes!("has-text-weight-semibold") route=Route::Author { id: post.meta.author.seed }>
|
||||
<Link<Route> classes={classes!("has-text-weight-semibold")} route={Route::Author { id: post.meta.author.seed }}>
|
||||
{ &post.meta.author.name }
|
||||
</Link<Route>>
|
||||
</h2>
|
||||
@ -78,12 +78,12 @@ impl Post {
|
||||
<article class="media block box my-6">
|
||||
<figure class="media-left">
|
||||
<p class="image is-64x64">
|
||||
<img src=Cow::Owned(quote.author.image_url.clone()) loading="lazy" />
|
||||
<img src={Cow::Owned(quote.author.image_url.clone())} loading="lazy" />
|
||||
</p>
|
||||
</figure>
|
||||
<div class="media-content">
|
||||
<div class="content">
|
||||
<Link<Route> classes=classes!("is-size-5") route=Route::Author { id: quote.author.seed }>
|
||||
<Link<Route> classes={classes!("is-size-5")} route={Route::Author { id: quote.author.seed }}>
|
||||
<strong>{ "e.author.name }</strong>
|
||||
</Link<Route>>
|
||||
<p class="is-family-secondary">
|
||||
@ -98,7 +98,7 @@ impl Post {
|
||||
fn render_section_hero(&self, section: &content::Section) -> Html {
|
||||
html! {
|
||||
<section class="hero is-dark has-background mt-6 mb-3">
|
||||
<img class="hero-background is-transparent" src=Cow::Owned(section.image_url.clone()) loading="lazy" />
|
||||
<img class="hero-background is-transparent" src={Cow::Owned(section.image_url.clone())} loading="lazy" />
|
||||
<div class="hero-body">
|
||||
<div class="container">
|
||||
<h2 class="subtitle">{ §ion.title }</h2>
|
||||
|
||||
@ -48,9 +48,9 @@ impl Component for PostList {
|
||||
<h2 class="subtitle">{ "All of our quality writing in one place" }</h2>
|
||||
{ self.view_posts() }
|
||||
<Pagination
|
||||
page=page
|
||||
total_pages=TOTAL_PAGES
|
||||
on_switch_page=self.link.callback(Msg::ShowPage)
|
||||
page={page}
|
||||
total_pages={TOTAL_PAGES}
|
||||
on_switch_page={self.link.callback(Msg::ShowPage)}
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
@ -62,7 +62,7 @@ impl PostList {
|
||||
let mut cards = (0..ITEMS_PER_PAGE).map(|seed_offset| {
|
||||
html! {
|
||||
<li class="list-item mb-5">
|
||||
<PostCard seed=start_seed + seed_offset />
|
||||
<PostCard seed={start_seed + seed_offset} />
|
||||
</li>
|
||||
}
|
||||
});
|
||||
|
||||
@ -64,10 +64,10 @@ impl Component for Model {
|
||||
fn view(&self) -> Html {
|
||||
html! {
|
||||
<>
|
||||
<TextInput value="New post" onsubmit=self.link.callback(Msg::CreatePost) />
|
||||
<TextInput value="New post" onsubmit={self.link.callback(Msg::CreatePost)} />
|
||||
|
||||
<div>
|
||||
{ for self.post_ids.iter().map(|&id| html!{ <Post key=id id=id /> }) }
|
||||
{ for self.post_ids.iter().map(|&id| html!{ <Post key={id} id={id} /> }) }
|
||||
</div>
|
||||
</>
|
||||
}
|
||||
|
||||
@ -72,8 +72,8 @@ impl Component for Post {
|
||||
<h2>{ format!("Post #{}", self.id) }</h2>
|
||||
<p>{text}</p>
|
||||
|
||||
<TextInput value=text.to_owned() onsubmit=self.link.callback(Msg::UpdateText) />
|
||||
<button onclick=self.link.callback(|_| Msg::Delete)>
|
||||
<TextInput value={text.to_owned()} onsubmit={self.link.callback(Msg::UpdateText)} />
|
||||
<button onclick={self.link.callback(|_| Msg::Delete)}>
|
||||
{ "Delete" }
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@ -57,12 +57,12 @@ impl Component for TextInput {
|
||||
html! {
|
||||
<input
|
||||
type="text"
|
||||
value=self.text.clone()
|
||||
oninput=self.link.callback(|e: InputData| Msg::SetText(e.value))
|
||||
onkeydown=self.link.batch_callback(move |e: KeyboardEvent| {
|
||||
value={self.text.clone()}
|
||||
oninput={self.link.callback(|e: InputData| Msg::SetText(e.value))}
|
||||
onkeydown={self.link.batch_callback(move |e: KeyboardEvent| {
|
||||
e.stop_propagation();
|
||||
if e.key() == "Enter" { Some(Msg::Submit) } else { None }
|
||||
})
|
||||
})}
|
||||
/>
|
||||
}
|
||||
}
|
||||
|
||||
@ -131,13 +131,13 @@ impl Component for Model {
|
||||
html! {
|
||||
<>
|
||||
<div id="buttons">
|
||||
<button disabled=has_job onclick=self.link.callback(|_| Msg::StartTimeout)>
|
||||
<button disabled={has_job} onclick={self.link.callback(|_| Msg::StartTimeout)}>
|
||||
{ "Start Timeout" }
|
||||
</button>
|
||||
<button disabled=has_job onclick=self.link.callback(|_| Msg::StartInterval)>
|
||||
<button disabled={has_job} onclick={self.link.callback(|_| Msg::StartInterval)}>
|
||||
{ "Start Interval" }
|
||||
</button>
|
||||
<button disabled=!has_job onclick=self.link.callback(|_| Msg::Cancel)>
|
||||
<button disabled={!has_job} onclick={self.link.callback(|_| Msg::Cancel)}>
|
||||
{ "Cancel!" }
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@ -124,20 +124,20 @@ impl Component for Model {
|
||||
<h1>{ "todos" }</h1>
|
||||
{ self.view_input() }
|
||||
</header>
|
||||
<section class=classes!("main", hidden_class)>
|
||||
<section class={classes!("main", hidden_class)}>
|
||||
<input
|
||||
type="checkbox"
|
||||
class="toggle-all"
|
||||
id="toggle-all"
|
||||
checked=self.state.is_all_completed()
|
||||
onclick=self.link.callback(|_| Msg::ToggleAll)
|
||||
checked={self.state.is_all_completed()}
|
||||
onclick={self.link.callback(|_| Msg::ToggleAll)}
|
||||
/>
|
||||
<label for="toggle-all" />
|
||||
<ul class="todo-list">
|
||||
{ for self.state.entries.iter().filter(|e| self.state.filter.fits(e)).enumerate().map(|e| self.view_entry(e)) }
|
||||
</ul>
|
||||
</section>
|
||||
<footer class=classes!("footer", hidden_class)>
|
||||
<footer class={classes!("footer", hidden_class)}>
|
||||
<span class="todo-count">
|
||||
<strong>{ self.state.total() }</strong>
|
||||
{ " item(s) left" }
|
||||
@ -145,7 +145,7 @@ impl Component for Model {
|
||||
<ul class="filters">
|
||||
{ for Filter::iter().map(|flt| self.view_filter(flt)) }
|
||||
</ul>
|
||||
<button class="clear-completed" onclick=self.link.callback(|_| Msg::ClearCompleted)>
|
||||
<button class="clear-completed" onclick={self.link.callback(|_| Msg::ClearCompleted)}>
|
||||
{ format!("Clear completed ({})", self.state.total_completed()) }
|
||||
</button>
|
||||
</footer>
|
||||
@ -169,9 +169,9 @@ impl Model {
|
||||
};
|
||||
html! {
|
||||
<li>
|
||||
<a class=cls
|
||||
href=filter.as_href()
|
||||
onclick=self.link.callback(move |_| Msg::SetFilter(filter))
|
||||
<a class={cls}
|
||||
href={filter.as_href()}
|
||||
onclick={self.link.callback(move |_| Msg::SetFilter(filter))}
|
||||
>
|
||||
{ filter }
|
||||
</a>
|
||||
@ -186,11 +186,11 @@ impl Model {
|
||||
<input
|
||||
class="new-todo"
|
||||
placeholder="What needs to be done?"
|
||||
value=self.state.value.clone()
|
||||
oninput=self.link.callback(|e: InputData| Msg::Update(e.value))
|
||||
onkeypress=self.link.batch_callback(|e: KeyboardEvent| {
|
||||
value={self.state.value.clone()}
|
||||
oninput={self.link.callback(|e: InputData| Msg::Update(e.value))}
|
||||
onkeypress={self.link.batch_callback(|e: KeyboardEvent| {
|
||||
if e.key() == "Enter" { Some(Msg::Add) } else { None }
|
||||
})
|
||||
})}
|
||||
/>
|
||||
/* Or multiline:
|
||||
<ul>
|
||||
@ -209,16 +209,16 @@ impl Model {
|
||||
class.push(" completed");
|
||||
}
|
||||
html! {
|
||||
<li class=class>
|
||||
<li class={class}>
|
||||
<div class="view">
|
||||
<input
|
||||
type="checkbox"
|
||||
class="toggle"
|
||||
checked=entry.completed
|
||||
onclick=self.link.callback(move |_| Msg::Toggle(idx))
|
||||
checked={entry.completed}
|
||||
onclick={self.link.callback(move |_| Msg::Toggle(idx))}
|
||||
/>
|
||||
<label ondblclick=self.link.callback(move |_| Msg::ToggleEdit(idx))>{ &entry.description }</label>
|
||||
<button class="destroy" onclick=self.link.callback(move |_| Msg::Remove(idx)) />
|
||||
<label ondblclick={self.link.callback(move |_| Msg::ToggleEdit(idx))}>{ &entry.description }</label>
|
||||
<button class="destroy" onclick={self.link.callback(move |_| Msg::Remove(idx))} />
|
||||
</div>
|
||||
{ self.view_entry_edit_input((idx, &entry)) }
|
||||
</li>
|
||||
@ -231,14 +231,14 @@ impl Model {
|
||||
<input
|
||||
class="edit"
|
||||
type="text"
|
||||
ref=self.focus_ref.clone()
|
||||
value=self.state.edit_value.clone()
|
||||
onmouseover=self.link.callback(|_| Msg::Focus)
|
||||
oninput=self.link.callback(|e: InputData| Msg::UpdateEdit(e.value))
|
||||
onblur=self.link.callback(move |_| Msg::Edit(idx))
|
||||
onkeypress=self.link.batch_callback(move |e: KeyboardEvent| {
|
||||
ref={self.focus_ref.clone()}
|
||||
value={self.state.edit_value.clone()}
|
||||
onmouseover={self.link.callback(|_| Msg::Focus)}
|
||||
oninput={self.link.callback(|e: InputData| Msg::UpdateEdit(e.value))}
|
||||
onblur={self.link.callback(move |_| Msg::Edit(idx))}
|
||||
onkeypress={self.link.batch_callback(move |e: KeyboardEvent| {
|
||||
if e.key() == "Enter" { Some(Msg::Edit(idx)) } else { None }
|
||||
})
|
||||
})}
|
||||
/>
|
||||
}
|
||||
} else {
|
||||
|
||||
@ -65,10 +65,10 @@ impl Component for Model {
|
||||
html! {
|
||||
<div>
|
||||
<h3>{ format!("{} received <{}>", self.selector, self.title) }</h3>
|
||||
<button onclick=self.link.callback(|_| Msg::SendToOpposite("One".into()))>{ "One" }</button>
|
||||
<button onclick=self.link.callback(|_| Msg::SendToOpposite("Two".into()))>{ "Two" }</button>
|
||||
<button onclick=self.link.callback(|_| Msg::SendToOpposite("Three".into()))>{ "Three" }</button>
|
||||
<button onclick=self.link.callback(|_| Msg::SendToOpposite("Ping".into()))>{ "Ping" }</button>
|
||||
<button onclick={self.link.callback(|_| Msg::SendToOpposite("One".into()))}>{ "One" }</button>
|
||||
<button onclick={self.link.callback(|_| Msg::SendToOpposite("Two".into()))}>{ "Two" }</button>
|
||||
<button onclick={self.link.callback(|_| Msg::SendToOpposite("Three".into()))}>{ "Three" }</button>
|
||||
<button onclick={self.link.callback(|_| Msg::SendToOpposite("Ping".into()))}>{ "Ping" }</button>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
@ -76,7 +76,7 @@ impl Component for Model {
|
||||
|
||||
fn view(&self) -> Html {
|
||||
html! {
|
||||
<canvas ref=self.node_ref.clone() />
|
||||
<canvas ref={self.node_ref.clone()} />
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -37,7 +37,7 @@
|
||||
//!
|
||||
//! html! {
|
||||
//! <div>
|
||||
//! <button onclick=self.link.callback(|_| Msg::Submit)>
|
||||
//! <button onclick={self.link.callback(|_| Msg::Submit)}>
|
||||
//! { "Submit" }
|
||||
//! </button>
|
||||
//! <>
|
||||
|
||||
@ -8,7 +8,7 @@ use std::{
|
||||
};
|
||||
use syn::{
|
||||
parse::{Parse, ParseStream},
|
||||
Expr, Token,
|
||||
Block, Expr, ExprBlock, Stmt, Token,
|
||||
};
|
||||
|
||||
pub enum PropPunct {
|
||||
@ -45,7 +45,7 @@ impl Parse for Prop {
|
||||
"expected an expression following this equals sign",
|
||||
));
|
||||
}
|
||||
let value = input.parse::<Expr>()?;
|
||||
let value = strip_braces(input.parse::<Expr>()?)?;
|
||||
Ok(Self {
|
||||
label,
|
||||
punct: Some(PropPunct::Eq(equals)),
|
||||
@ -54,6 +54,30 @@ impl Parse for Prop {
|
||||
}
|
||||
}
|
||||
|
||||
fn strip_braces(expr: Expr) -> syn::Result<Expr> {
|
||||
match expr {
|
||||
Expr::Block(ExprBlock { block: Block { mut stmts, .. }, .. }) if stmts.len() == 1 => {
|
||||
let stmt = stmts.remove(0);
|
||||
match stmt {
|
||||
Stmt::Expr(expr) => Ok(expr),
|
||||
Stmt::Semi(_expr, semi) => Err(syn::Error::new_spanned(
|
||||
semi,
|
||||
"only an expression may be assigned as a property. Consider removing this semicolon",
|
||||
)),
|
||||
_ => Err(syn::Error::new_spanned(
|
||||
stmt,
|
||||
"only an expression may be assigned as a property",
|
||||
))
|
||||
}
|
||||
}
|
||||
Expr::Lit(_) | Expr::Block(_) => Ok(expr),
|
||||
_ => Err(syn::Error::new_spanned(
|
||||
&expr,
|
||||
"the property value must be either a literal or enclosed in braces. Consider adding braces around your expression.".to_string(),
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
/// List of props sorted in alphabetical order*.
|
||||
///
|
||||
/// \*The "children" prop always comes last to match the behaviour of the `Properties` derive macro.
|
||||
|
||||
@ -59,17 +59,18 @@ fn compile_fail() {
|
||||
html! { <Child with props > };
|
||||
let (p1, p2);
|
||||
html! { <Child with p1 with p2 /> };
|
||||
html! { <Child with props ref=() ref=() /> };
|
||||
html! { <Child with props ref=() ref=() value=1 /> };
|
||||
html! { <Child with props ref=() value=1 ref=() /> };
|
||||
html! { <Child with props value=1 ref=() ref=() /> };
|
||||
html! { <Child value=1 with props ref=() ref=() /> };
|
||||
html! { <Child value=1 ref=() with props ref=() /> };
|
||||
html! { <Child ref=() ref=() value=1 with props /> };
|
||||
html! { <Child with props ref={()} ref={()} /> };
|
||||
html! { <Child with props ref={()} ref={()} value=1 /> };
|
||||
html! { <Child with props ref={()} value=1 ref={()} /> };
|
||||
html! { <Child with props value=1 ref={()} ref={()} /> };
|
||||
html! { <Child value=1 with props ref={()} ref={()} /> };
|
||||
html! { <Child value=1 ref={()} with props ref={()} /> };
|
||||
html! { <Child ref={()} ref={()} value=1 with props /> };
|
||||
html! { <Child with blah /> };
|
||||
html! { <Child value=1 with props /> };
|
||||
html! { <Child with props value=1 /> };
|
||||
html! { <Child type=0 /> };
|
||||
html! { <Child ref=() /> };
|
||||
html! { <Child invalid-prop-name=0 /> };
|
||||
html! { <Child unknown="unknown" /> };
|
||||
html! { <Child string= /> };
|
||||
@ -77,8 +78,8 @@ fn compile_fail() {
|
||||
html! { <Child int=1 string={} /> };
|
||||
html! { <Child int=1 string=3 /> };
|
||||
html! { <Child int=1 string={3} /> };
|
||||
html! { <Child int=1 ref=() /> };
|
||||
html! { <Child int=1 ref=() ref=() /> };
|
||||
html! { <Child int=1 ref={()} /> };
|
||||
html! { <Child int=1 ref={()} ref={()} /> };
|
||||
html! { <Child int=0u32 /> };
|
||||
html! { <Child string="abc" /> };
|
||||
html! { </Child> };
|
||||
@ -102,7 +103,7 @@ fn compile_fail() {
|
||||
// using `children` as a prop while simultaneously passing children using the syntactic sugar
|
||||
let children = ChildrenRenderer::new(vec![html_nested! { <Child int=0 /> }]);
|
||||
html! {
|
||||
<ChildContainer children=children>
|
||||
<ChildContainer children={children}>
|
||||
<Child int=1 />
|
||||
</ChildContainer>
|
||||
};
|
||||
|
||||
@ -35,46 +35,46 @@ error: there are two `with <props>` definitions for this component (note: you ca
|
||||
| ^^^^^^^
|
||||
|
||||
error: `ref` can only be set once
|
||||
--> $DIR/component-fail.rs:62:38
|
||||
--> $DIR/component-fail.rs:62:40
|
||||
|
|
||||
62 | html! { <Child with props ref=() ref=() /> };
|
||||
| ^^^
|
||||
62 | html! { <Child with props ref={()} ref={()} /> };
|
||||
| ^^^
|
||||
|
||||
error: `ref` can only be set once
|
||||
--> $DIR/component-fail.rs:63:38
|
||||
--> $DIR/component-fail.rs:63:40
|
||||
|
|
||||
63 | html! { <Child with props ref=() ref=() value=1 /> };
|
||||
| ^^^
|
||||
63 | html! { <Child with props ref={()} ref={()} value=1 /> };
|
||||
| ^^^
|
||||
|
||||
error: Using the `with props` syntax in combination with named props is not allowed (note: this does not apply to special props like `ref` and `key`)
|
||||
--> $DIR/component-fail.rs:64:38
|
||||
--> $DIR/component-fail.rs:64:40
|
||||
|
|
||||
64 | html! { <Child with props ref=() value=1 ref=() /> };
|
||||
| ^^^^^
|
||||
64 | html! { <Child with props ref={()} value=1 ref={()} /> };
|
||||
| ^^^^^
|
||||
|
||||
error: Using the `with props` syntax in combination with named props is not allowed (note: this does not apply to special props like `ref` and `key`)
|
||||
--> $DIR/component-fail.rs:65:31
|
||||
|
|
||||
65 | html! { <Child with props value=1 ref=() ref=() /> };
|
||||
65 | html! { <Child with props value=1 ref={()} ref={()} /> };
|
||||
| ^^^^^
|
||||
|
||||
error: Using the `with props` syntax in combination with named props is not allowed (note: this does not apply to special props like `ref` and `key`)
|
||||
--> $DIR/component-fail.rs:66:20
|
||||
|
|
||||
66 | html! { <Child value=1 with props ref=() ref=() /> };
|
||||
66 | html! { <Child value=1 with props ref={()} ref={()} /> };
|
||||
| ^^^^^
|
||||
|
||||
error: Using the `with props` syntax in combination with named props is not allowed (note: this does not apply to special props like `ref` and `key`)
|
||||
--> $DIR/component-fail.rs:67:20
|
||||
|
|
||||
67 | html! { <Child value=1 ref=() with props ref=() /> };
|
||||
67 | html! { <Child value=1 ref={()} with props ref={()} /> };
|
||||
| ^^^^^
|
||||
|
||||
error: `ref` can only be set once
|
||||
--> $DIR/component-fail.rs:68:27
|
||||
--> $DIR/component-fail.rs:68:29
|
||||
|
|
||||
68 | html! { <Child ref=() ref=() value=1 with props /> };
|
||||
| ^^^
|
||||
68 | html! { <Child ref={()} ref={()} value=1 with props /> };
|
||||
| ^^^
|
||||
|
||||
error: Using the `with props` syntax in combination with named props is not allowed (note: this does not apply to special props like `ref` and `key`)
|
||||
--> $DIR/component-fail.rs:70:20
|
||||
@ -99,64 +99,70 @@ help: you can escape reserved keywords to use them as identifiers
|
||||
72 | html! { <Child r#type=0 /> };
|
||||
| ^^^^^^
|
||||
|
||||
error: expected a valid Rust identifier
|
||||
--> $DIR/component-fail.rs:73:20
|
||||
error: the property value must be either a literal or enclosed in braces. Consider adding braces around your expression.
|
||||
--> $DIR/component-fail.rs:73:24
|
||||
|
|
||||
73 | html! { <Child invalid-prop-name=0 /> };
|
||||
73 | html! { <Child ref=() /> };
|
||||
| ^^
|
||||
|
||||
error: expected a valid Rust identifier
|
||||
--> $DIR/component-fail.rs:74:20
|
||||
|
|
||||
74 | html! { <Child invalid-prop-name=0 /> };
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: expected an expression following this equals sign
|
||||
--> $DIR/component-fail.rs:75:26
|
||||
--> $DIR/component-fail.rs:76:26
|
||||
|
|
||||
75 | html! { <Child string= /> };
|
||||
76 | html! { <Child string= /> };
|
||||
| ^
|
||||
|
||||
error: `int` can only be specified once but is given here again
|
||||
--> $DIR/component-fail.rs:76:26
|
||||
--> $DIR/component-fail.rs:77:26
|
||||
|
|
||||
76 | html! { <Child int=1 int=2 int=3 /> };
|
||||
77 | html! { <Child int=1 int=2 int=3 /> };
|
||||
| ^^^
|
||||
|
||||
error: `int` can only be specified once but is given here again
|
||||
--> $DIR/component-fail.rs:76:32
|
||||
--> $DIR/component-fail.rs:77:32
|
||||
|
|
||||
76 | html! { <Child int=1 int=2 int=3 /> };
|
||||
77 | html! { <Child int=1 int=2 int=3 /> };
|
||||
| ^^^
|
||||
|
||||
error: `ref` can only be specified once
|
||||
--> $DIR/component-fail.rs:81:26
|
||||
--> $DIR/component-fail.rs:82:26
|
||||
|
|
||||
81 | html! { <Child int=1 ref=() ref=() /> };
|
||||
82 | html! { <Child int=1 ref={()} ref={()} /> };
|
||||
| ^^^
|
||||
|
||||
error: this closing tag has no corresponding opening tag
|
||||
--> $DIR/component-fail.rs:84:13
|
||||
--> $DIR/component-fail.rs:85:13
|
||||
|
|
||||
84 | html! { </Child> };
|
||||
85 | html! { </Child> };
|
||||
| ^^^^^^^^
|
||||
|
||||
error: this opening tag has no corresponding closing tag
|
||||
--> $DIR/component-fail.rs:85:13
|
||||
--> $DIR/component-fail.rs:86:13
|
||||
|
|
||||
85 | html! { <Child><Child></Child> };
|
||||
86 | html! { <Child><Child></Child> };
|
||||
| ^^^^^^^
|
||||
|
||||
error: only one root html element is allowed (hint: you can wrap multiple html elements in a fragment `<></>`)
|
||||
--> $DIR/component-fail.rs:86:28
|
||||
--> $DIR/component-fail.rs:87:28
|
||||
|
|
||||
86 | html! { <Child></Child><Child></Child> };
|
||||
87 | html! { <Child></Child><Child></Child> };
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
error: cannot specify the `children` prop when the component already has children
|
||||
--> $DIR/component-fail.rs:105:25
|
||||
--> $DIR/component-fail.rs:106:25
|
||||
|
|
||||
105 | <ChildContainer children=children>
|
||||
106 | <ChildContainer children={children}>
|
||||
| ^^^^^^^^
|
||||
|
||||
error: only one root html element is allowed (hint: you can wrap multiple html elements in a fragment `<></>`)
|
||||
--> $DIR/component-fail.rs:112:9
|
||||
--> $DIR/component-fail.rs:113:9
|
||||
|
|
||||
112 | <span>{ 2 }</span>
|
||||
113 | <span>{ 2 }</span>
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0425]: cannot find value `blah` in this scope
|
||||
@ -183,32 +189,32 @@ error[E0599]: no method named `r#type` found for struct `ChildPropertiesBuilder<
|
||||
| ^^^^ method not found in `ChildPropertiesBuilder<ChildPropertiesBuilderStep_missing_required_prop_int>`
|
||||
|
||||
error[E0609]: no field `unknown` on type `ChildProperties`
|
||||
--> $DIR/component-fail.rs:74:20
|
||||
--> $DIR/component-fail.rs:75:20
|
||||
|
|
||||
74 | html! { <Child unknown="unknown" /> };
|
||||
75 | html! { <Child unknown="unknown" /> };
|
||||
| ^^^^^^^ unknown field
|
||||
|
|
||||
= note: available fields are: `string`, `int`
|
||||
|
||||
error[E0599]: no method named `unknown` found for struct `ChildPropertiesBuilder<ChildPropertiesBuilderStep_missing_required_prop_int>` in the current scope
|
||||
--> $DIR/component-fail.rs:74:20
|
||||
--> $DIR/component-fail.rs:75:20
|
||||
|
|
||||
4 | #[derive(Clone, Properties, PartialEq)]
|
||||
| ---------- method `unknown` not found for this
|
||||
...
|
||||
74 | html! { <Child unknown="unknown" /> };
|
||||
75 | html! { <Child unknown="unknown" /> };
|
||||
| ^^^^^^^ method not found in `ChildPropertiesBuilder<ChildPropertiesBuilderStep_missing_required_prop_int>`
|
||||
|
||||
error[E0277]: the trait bound `(): IntoPropValue<String>` is not satisfied
|
||||
--> $DIR/component-fail.rs:77:33
|
||||
--> $DIR/component-fail.rs:78:33
|
||||
|
|
||||
77 | html! { <Child int=1 string={} /> };
|
||||
78 | html! { <Child int=1 string={} /> };
|
||||
| ^^ the trait `IntoPropValue<String>` is not implemented for `()`
|
||||
|
||||
error[E0277]: the trait bound `{integer}: IntoPropValue<String>` is not satisfied
|
||||
--> $DIR/component-fail.rs:78:33
|
||||
--> $DIR/component-fail.rs:79:33
|
||||
|
|
||||
78 | html! { <Child int=1 string=3 /> };
|
||||
79 | html! { <Child int=1 string=3 /> };
|
||||
| ^ the trait `IntoPropValue<String>` is not implemented for `{integer}`
|
||||
|
|
||||
= help: the following implementations were found:
|
||||
@ -219,10 +225,10 @@ error[E0277]: the trait bound `{integer}: IntoPropValue<String>` is not satisfie
|
||||
and 11 others
|
||||
|
||||
error[E0277]: the trait bound `{integer}: IntoPropValue<String>` is not satisfied
|
||||
--> $DIR/component-fail.rs:79:26
|
||||
--> $DIR/component-fail.rs:80:34
|
||||
|
|
||||
79 | html! { <Child int=1 string={3} /> };
|
||||
| ^^^^^^ the trait `IntoPropValue<String>` is not implemented for `{integer}`
|
||||
80 | html! { <Child int=1 string={3} /> };
|
||||
| ^ the trait `IntoPropValue<String>` is not implemented for `{integer}`
|
||||
|
|
||||
= help: the following implementations were found:
|
||||
<&'static str as IntoPropValue<Cow<'static, str>>>
|
||||
@ -232,91 +238,91 @@ error[E0277]: the trait bound `{integer}: IntoPropValue<String>` is not satisfie
|
||||
and 11 others
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/component-fail.rs:80:30
|
||||
--> $DIR/component-fail.rs:81:31
|
||||
|
|
||||
80 | html! { <Child int=1 ref=() /> };
|
||||
| ^^ expected struct `NodeRef`, found `()`
|
||||
81 | html! { <Child int=1 ref={()} /> };
|
||||
| ^^ expected struct `NodeRef`, found `()`
|
||||
|
||||
error[E0277]: the trait bound `u32: IntoPropValue<i32>` is not satisfied
|
||||
--> $DIR/component-fail.rs:82:24
|
||||
--> $DIR/component-fail.rs:83:24
|
||||
|
|
||||
82 | html! { <Child int=0u32 /> };
|
||||
83 | html! { <Child int=0u32 /> };
|
||||
| ^^^^ the trait `IntoPropValue<i32>` is not implemented for `u32`
|
||||
|
||||
error[E0599]: no method named `string` found for struct `ChildPropertiesBuilder<ChildPropertiesBuilderStep_missing_required_prop_int>` in the current scope
|
||||
--> $DIR/component-fail.rs:83:20
|
||||
--> $DIR/component-fail.rs:84:20
|
||||
|
|
||||
4 | #[derive(Clone, Properties, PartialEq)]
|
||||
| ---------- method `string` not found for this
|
||||
...
|
||||
83 | html! { <Child string="abc" /> };
|
||||
84 | html! { <Child string="abc" /> };
|
||||
| ^^^^^^ method not found in `ChildPropertiesBuilder<ChildPropertiesBuilderStep_missing_required_prop_int>`
|
||||
|
||||
error[E0609]: no field `children` on type `ChildProperties`
|
||||
--> $DIR/component-fail.rs:87:14
|
||||
--> $DIR/component-fail.rs:88:14
|
||||
|
|
||||
87 | html! { <Child>{ "Not allowed" }</Child> };
|
||||
88 | html! { <Child>{ "Not allowed" }</Child> };
|
||||
| ^^^^^ unknown field
|
||||
|
|
||||
= note: available fields are: `string`, `int`
|
||||
|
||||
error[E0599]: no method named `children` found for struct `ChildPropertiesBuilder<ChildPropertiesBuilderStep_missing_required_prop_int>` in the current scope
|
||||
--> $DIR/component-fail.rs:87:14
|
||||
--> $DIR/component-fail.rs:88:14
|
||||
|
|
||||
4 | #[derive(Clone, Properties, PartialEq)]
|
||||
| ---------- method `children` not found for this
|
||||
...
|
||||
87 | html! { <Child>{ "Not allowed" }</Child> };
|
||||
88 | html! { <Child>{ "Not allowed" }</Child> };
|
||||
| ^^^^^ method not found in `ChildPropertiesBuilder<ChildPropertiesBuilderStep_missing_required_prop_int>`
|
||||
|
||||
error[E0609]: no field `children` on type `ChildProperties`
|
||||
--> $DIR/component-fail.rs:91:10
|
||||
--> $DIR/component-fail.rs:92:10
|
||||
|
|
||||
91 | <Child with ChildProperties { string: "hello".to_owned(), int: 5 }>
|
||||
92 | <Child with ChildProperties { string: "hello".to_owned(), int: 5 }>
|
||||
| ^^^^^ unknown field
|
||||
|
|
||||
= note: available fields are: `string`, `int`
|
||||
|
||||
error[E0599]: no method named `build` found for struct `ChildContainerPropertiesBuilder<ChildContainerPropertiesBuilderStep_missing_required_prop_children>` in the current scope
|
||||
--> $DIR/component-fail.rs:96:14
|
||||
|
|
||||
30 | #[derive(Clone, Properties)]
|
||||
| ---------- method `build` not found for this
|
||||
...
|
||||
96 | html! { <ChildContainer /> };
|
||||
| ^^^^^^^^^^^^^^ method not found in `ChildContainerPropertiesBuilder<ChildContainerPropertiesBuilderStep_missing_required_prop_children>`
|
||||
|
||||
error[E0599]: no method named `build` found for struct `ChildContainerPropertiesBuilder<ChildContainerPropertiesBuilderStep_missing_required_prop_children>` in the current scope
|
||||
--> $DIR/component-fail.rs:97:14
|
||||
|
|
||||
30 | #[derive(Clone, Properties)]
|
||||
| ---------- method `build` not found for this
|
||||
...
|
||||
97 | html! { <ChildContainer></ChildContainer> };
|
||||
97 | html! { <ChildContainer /> };
|
||||
| ^^^^^^^^^^^^^^ method not found in `ChildContainerPropertiesBuilder<ChildContainerPropertiesBuilderStep_missing_required_prop_children>`
|
||||
|
||||
error[E0599]: no method named `build` found for struct `ChildContainerPropertiesBuilder<ChildContainerPropertiesBuilderStep_missing_required_prop_children>` in the current scope
|
||||
--> $DIR/component-fail.rs:98:14
|
||||
|
|
||||
30 | #[derive(Clone, Properties)]
|
||||
| ---------- method `build` not found for this
|
||||
...
|
||||
98 | html! { <ChildContainer></ChildContainer> };
|
||||
| ^^^^^^^^^^^^^^ method not found in `ChildContainerPropertiesBuilder<ChildContainerPropertiesBuilderStep_missing_required_prop_children>`
|
||||
|
||||
error[E0277]: the trait bound `VChild<Child>: From<yew::virtual_dom::VText>` is not satisfied
|
||||
--> $DIR/component-fail.rs:98:31
|
||||
--> $DIR/component-fail.rs:99:31
|
||||
|
|
||||
98 | html! { <ChildContainer>{ "Not allowed" }</ChildContainer> };
|
||||
99 | html! { <ChildContainer>{ "Not allowed" }</ChildContainer> };
|
||||
| ^^^^^^^^^^^^^ the trait `From<yew::virtual_dom::VText>` is not implemented for `VChild<Child>`
|
||||
|
|
||||
= note: required because of the requirements on the impl of `Into<VChild<Child>>` for `yew::virtual_dom::VText`
|
||||
= note: required by `into`
|
||||
|
||||
error[E0277]: the trait bound `VChild<Child>: From<VNode>` is not satisfied
|
||||
--> $DIR/component-fail.rs:99:29
|
||||
|
|
||||
99 | html! { <ChildContainer><></></ChildContainer> };
|
||||
| ^ the trait `From<VNode>` is not implemented for `VChild<Child>`
|
||||
|
|
||||
= note: required because of the requirements on the impl of `Into<VChild<Child>>` for `VNode`
|
||||
= note: required by `into`
|
||||
--> $DIR/component-fail.rs:100:29
|
||||
|
|
||||
100 | html! { <ChildContainer><></></ChildContainer> };
|
||||
| ^ the trait `From<VNode>` is not implemented for `VChild<Child>`
|
||||
|
|
||||
= note: required because of the requirements on the impl of `Into<VChild<Child>>` for `VNode`
|
||||
= note: required by `into`
|
||||
|
||||
error[E0277]: the trait bound `VChild<Child>: From<VNode>` is not satisfied
|
||||
--> $DIR/component-fail.rs:100:30
|
||||
--> $DIR/component-fail.rs:101:30
|
||||
|
|
||||
100 | html! { <ChildContainer><other /></ChildContainer> };
|
||||
101 | html! { <ChildContainer><other /></ChildContainer> };
|
||||
| ^^^^^ the trait `From<VNode>` is not implemented for `VChild<Child>`
|
||||
|
|
||||
= note: required because of the requirements on the impl of `Into<VChild<Child>>` for `VNode`
|
||||
|
||||
@ -152,8 +152,8 @@ fn compile_pass() {
|
||||
html! {
|
||||
<>
|
||||
<Child with props />
|
||||
<Child ref=node_ref.clone() with yew::props!(Child::Properties { int: 5 }) />
|
||||
<Child with <Child as Component>::Properties::default() ref=node_ref />
|
||||
<Child ref={node_ref.clone()} with yew::props!(Child::Properties { int: 5 }) />
|
||||
<Child with <Child as Component>::Properties::default() ref={node_ref} />
|
||||
</>
|
||||
};
|
||||
|
||||
@ -165,29 +165,31 @@ fn compile_pass() {
|
||||
<Child int=1 vec={vec![1]} />
|
||||
<Child string={String::from("child")} int=1 />
|
||||
|
||||
<Child opt_str=String::from("child") int=1 />
|
||||
<Child opt_str=Some(String::from("child")) int=1 />
|
||||
<Child opt_str="child" int=1 />
|
||||
<Child opt_str={String::from("child")} int=1 />
|
||||
<Child opt_str={Some("child")} int=1 />
|
||||
<Child opt_str={Some(String::from("child"))} int=1 />
|
||||
</>
|
||||
};
|
||||
|
||||
let name_expr = "child";
|
||||
html! {
|
||||
<Child int=1 string=name_expr />
|
||||
<Child int=1 string={name_expr} />
|
||||
};
|
||||
|
||||
html! {
|
||||
<>
|
||||
<Child int=1 />
|
||||
<Child int=1 optional_callback=Some(Callback::from(|_| ())) />
|
||||
<Child int=1 optional_callback=Callback::from(|_| ()) />
|
||||
<Child int=1 optional_callback=None::<Callback<_>> />
|
||||
<Child int=1 optional_callback={Some(Callback::from(|_| ()))} />
|
||||
<Child int=1 optional_callback={Callback::from(|_| ())} />
|
||||
<Child int=1 optional_callback={None::<Callback<_>>} />
|
||||
</>
|
||||
};
|
||||
|
||||
let node_ref = NodeRef::default();
|
||||
html! {
|
||||
<>
|
||||
<Child int=1 ref=node_ref />
|
||||
<Child int=1 ref={node_ref} />
|
||||
</>
|
||||
};
|
||||
|
||||
@ -209,9 +211,9 @@ fn compile_pass() {
|
||||
<scoped::Container int=2/>
|
||||
</scoped::Container>
|
||||
|
||||
<Container int=1 children=ChildrenRenderer::new(
|
||||
<Container int=1 children={ChildrenRenderer::new(
|
||||
vec![html!{ "String" }]
|
||||
) />
|
||||
)} />
|
||||
</>
|
||||
};
|
||||
|
||||
@ -235,7 +237,7 @@ fn compile_pass() {
|
||||
}
|
||||
{
|
||||
(0..2)
|
||||
.map(|i| { html_nested! { <Child int=i /> } })
|
||||
.map(|i| { html_nested! { <Child int={i} /> } })
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
</ChildContainer>
|
||||
|
||||
@ -30,31 +30,37 @@ fn compile_fail() {
|
||||
html! { <input disabled=true disabled=false /> };
|
||||
html! { <option selected=true selected=false /> };
|
||||
html! { <div class="first" class="second" /> };
|
||||
html! { <input ref=() ref=() /> };
|
||||
html! { <input ref={()} ref={()} /> };
|
||||
|
||||
// boolean attribute type mismatch
|
||||
html! { <input checked=1 /> };
|
||||
html! { <input checked=Some(false) /> };
|
||||
html! { <input checked={Some(false)} /> };
|
||||
html! { <input disabled=1 /> };
|
||||
html! { <input disabled=Some(true) /> };
|
||||
html! { <input disabled={Some(true)} /> };
|
||||
html! { <option selected=1 /> };
|
||||
|
||||
// normal attribute type mismatch
|
||||
html! { <input type=() /> };
|
||||
html! { <input value=() /> };
|
||||
html! { <a href=() /> };
|
||||
html! { <input string=NotToString /> };
|
||||
html! { <a media=Some(NotToString) /> };
|
||||
html! { <a href=Some(5) /> };
|
||||
html! { <input type={()} /> };
|
||||
html! { <input value={()} /> };
|
||||
html! { <a href={()} /> };
|
||||
html! { <input string={NotToString} /> };
|
||||
html! { <a media={Some(NotToString)} /> };
|
||||
html! { <a href={Some(5)} /> };
|
||||
|
||||
// listener type mismatch
|
||||
html! { <input onclick=1 /> };
|
||||
html! { <input onclick=Callback::from(|a: String| ()) /> };
|
||||
html! { <input onfocus=Some(5) /> };
|
||||
html! { <input onclick={Callback::from(|a: String| ()) /> };
|
||||
html! { <input onfocus={Some(5)} /> };
|
||||
|
||||
// NodeRef type mismatch
|
||||
html! { <input ref=() /> };
|
||||
html! { <input ref=Some(NodeRef::default()) /> };
|
||||
html! { <input ref={()} /> };
|
||||
html! { <input ref={Some(NodeRef::default())} /> };
|
||||
html! { <input onclick={Callback::from(|a: String| ())} /> };
|
||||
|
||||
html! { <input string={NotToString} /> };
|
||||
|
||||
html! { <input ref={()} /> };
|
||||
html! { <input ref={()} ref={()} /> };
|
||||
|
||||
// void element with children
|
||||
html! { <input type="text"></input> };
|
||||
@ -71,7 +77,19 @@ fn compile_fail() {
|
||||
html! { <@{55}></@> };
|
||||
|
||||
// check for deprecation warning
|
||||
html! { <div class={("deprecated", "warning")} /> };
|
||||
|
||||
// Missing curly braces
|
||||
html! { <div class=("deprecated", "warning") /> };
|
||||
html! { <input ref=() /> };
|
||||
html! { <input ref=() ref=() /> };
|
||||
html! { <input onfocus=Some(5) /> };
|
||||
html! { <input string=NotToString /> };
|
||||
html! { <a media=Some(NotToString) /> };
|
||||
html! { <a href=Some(5) /> };
|
||||
html! { <input type=() /> };
|
||||
html! { <input value=() /> };
|
||||
html! { <input string=NotToString /> };
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
||||
@ -1,3 +1,18 @@
|
||||
error: this file contains an unclosed delimiter
|
||||
--> $DIR/element-fail.rs:95:14
|
||||
|
|
||||
5 | fn compile_fail() {
|
||||
| - unclosed delimiter
|
||||
...
|
||||
52 | html! { <input onclick={Callback::from(|a: String| ()) /> };
|
||||
| - this delimiter might not be properly closed...
|
||||
...
|
||||
93 | }
|
||||
| - ...as it matches this but it has different indentation
|
||||
94 |
|
||||
95 | fn main() {}
|
||||
| ^
|
||||
|
||||
error: this opening tag has no corresponding closing tag
|
||||
--> $DIR/element-fail.rs:7:13
|
||||
|
|
||||
@ -103,46 +118,22 @@ error: `class` can only be specified once but is given here again
|
||||
error: `ref` can only be specified once
|
||||
--> $DIR/element-fail.rs:33:20
|
||||
|
|
||||
33 | html! { <input ref=() ref=() /> };
|
||||
33 | html! { <input ref={()} ref={()} /> };
|
||||
| ^^^
|
||||
|
||||
error: the tag `<input>` is a void element and cannot have children (hint: rewrite this as `<input/>`)
|
||||
--> $DIR/element-fail.rs:60:13
|
||||
error: unexpected end of input, expected token tree
|
||||
--> $DIR/element-fail.rs:52:5
|
||||
|
|
||||
60 | html! { <input type="text"></input> };
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: the tag `<iNpUt>` is a void element and cannot have children (hint: rewrite this as `<iNpUt/>`)
|
||||
--> $DIR/element-fail.rs:62:13
|
||||
52 | / html! { <input onclick={Callback::from(|a: String| ()) /> };
|
||||
53 | | html! { <input onfocus={Some(5)} /> };
|
||||
54 | |
|
||||
55 | | // NodeRef type mismatch
|
||||
... |
|
||||
92 | | html! { <input string=NotToString /> };
|
||||
93 | | }
|
||||
| |_^
|
||||
|
|
||||
62 | html! { <iNpUt type="text"></iNpUt> };
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: this dynamic tag is missing an expression block defining its value
|
||||
--> $DIR/element-fail.rs:65:14
|
||||
|
|
||||
65 | html! { <@></@> };
|
||||
| ^
|
||||
|
||||
error: this dynamic tag is missing an expression block defining its value
|
||||
--> $DIR/element-fail.rs:66:14
|
||||
|
|
||||
66 | html! { <@/> };
|
||||
| ^
|
||||
|
||||
error: dynamic closing tags must not have a body (hint: replace it with just `</@>`)
|
||||
--> $DIR/element-fail.rs:69:27
|
||||
|
|
||||
69 | html! { <@{"test"}></@{"test"}> };
|
||||
| ^^^^^^^^
|
||||
|
||||
warning: use of deprecated function `compile_fail::deprecated_use_of_class`: the use of `(...)` with the attribute `class` is deprecated and will be removed in version 0.19. Use the `classes!` macro instead.
|
||||
--> $DIR/element-fail.rs:74:24
|
||||
|
|
||||
74 | html! { <div class=("deprecated", "warning") /> };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(deprecated)]` on by default
|
||||
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/element-fail.rs:36:28
|
||||
@ -151,10 +142,10 @@ error[E0308]: mismatched types
|
||||
| ^ expected `bool`, found integer
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/element-fail.rs:37:28
|
||||
--> $DIR/element-fail.rs:37:29
|
||||
|
|
||||
37 | html! { <input checked=Some(false) /> };
|
||||
| ^^^^^^^^^^^ expected `bool`, found enum `Option`
|
||||
37 | html! { <input checked={Some(false)} /> };
|
||||
| ^^^^^^^^^^^ expected `bool`, found enum `Option`
|
||||
|
|
||||
= note: expected type `bool`
|
||||
found enum `Option<bool>`
|
||||
@ -166,10 +157,10 @@ error[E0308]: mismatched types
|
||||
| ^ expected `bool`, found integer
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/element-fail.rs:39:29
|
||||
--> $DIR/element-fail.rs:39:30
|
||||
|
|
||||
39 | html! { <input disabled=Some(true) /> };
|
||||
| ^^^^^^^^^^ expected `bool`, found enum `Option`
|
||||
39 | html! { <input disabled={Some(true)} /> };
|
||||
| ^^^^^^^^^^ expected `bool`, found enum `Option`
|
||||
|
|
||||
= note: expected type `bool`
|
||||
found enum `Option<bool>`
|
||||
@ -181,10 +172,10 @@ error[E0308]: mismatched types
|
||||
| ^ expected `bool`, found integer
|
||||
|
||||
error[E0277]: the trait bound `(): IntoPropValue<Option<Cow<'static, str>>>` is not satisfied
|
||||
--> $DIR/element-fail.rs:43:25
|
||||
--> $DIR/element-fail.rs:43:26
|
||||
|
|
||||
43 | html! { <input type=() /> };
|
||||
| ^^ the trait `IntoPropValue<Option<Cow<'static, str>>>` is not implemented for `()`
|
||||
43 | html! { <input type={()} /> };
|
||||
| ^^ the trait `IntoPropValue<Option<Cow<'static, str>>>` is not implemented for `()`
|
||||
|
|
||||
::: $WORKSPACE/packages/yew/src/virtual_dom/mod.rs
|
||||
|
|
||||
@ -192,18 +183,18 @@ error[E0277]: the trait bound `(): IntoPropValue<Option<Cow<'static, str>>>` is
|
||||
| -------------------------------- required by this bound in `PositionalAttr::new`
|
||||
|
||||
error[E0277]: the trait bound `(): IntoPropValue<Option<Cow<'static, str>>>` is not satisfied
|
||||
--> $DIR/element-fail.rs:44:26
|
||||
--> $DIR/element-fail.rs:44:27
|
||||
|
|
||||
44 | html! { <input value=() /> };
|
||||
| ^^ the trait `IntoPropValue<Option<Cow<'static, str>>>` is not implemented for `()`
|
||||
44 | html! { <input value={()} /> };
|
||||
| ^^ the trait `IntoPropValue<Option<Cow<'static, str>>>` is not implemented for `()`
|
||||
|
|
||||
= note: required by `into_prop_value`
|
||||
|
||||
error[E0277]: the trait bound `(): IntoPropValue<Option<Cow<'static, str>>>` is not satisfied
|
||||
--> $DIR/element-fail.rs:45:21
|
||||
--> $DIR/element-fail.rs:45:22
|
||||
|
|
||||
45 | html! { <a href=() /> };
|
||||
| ^^ the trait `IntoPropValue<Option<Cow<'static, str>>>` is not implemented for `()`
|
||||
45 | html! { <a href={()} /> };
|
||||
| ^^ the trait `IntoPropValue<Option<Cow<'static, str>>>` is not implemented for `()`
|
||||
|
|
||||
::: $WORKSPACE/packages/yew/src/virtual_dom/mod.rs
|
||||
|
|
||||
@ -211,10 +202,10 @@ error[E0277]: the trait bound `(): IntoPropValue<Option<Cow<'static, str>>>` is
|
||||
| -------------------------------- required by this bound in `PositionalAttr::new`
|
||||
|
||||
error[E0277]: the trait bound `NotToString: IntoPropValue<Option<Cow<'static, str>>>` is not satisfied
|
||||
--> $DIR/element-fail.rs:46:27
|
||||
--> $DIR/element-fail.rs:46:28
|
||||
|
|
||||
46 | html! { <input string=NotToString /> };
|
||||
| ^^^^^^^^^^^ the trait `IntoPropValue<Option<Cow<'static, str>>>` is not implemented for `NotToString`
|
||||
46 | html! { <input string={NotToString} /> };
|
||||
| ^^^^^^^^^^^ the trait `IntoPropValue<Option<Cow<'static, str>>>` is not implemented for `NotToString`
|
||||
|
|
||||
::: $WORKSPACE/packages/yew/src/virtual_dom/mod.rs
|
||||
|
|
||||
@ -222,10 +213,10 @@ error[E0277]: the trait bound `NotToString: IntoPropValue<Option<Cow<'static, st
|
||||
| -------------------------------- required by this bound in `PositionalAttr::new`
|
||||
|
||||
error[E0277]: the trait bound `Option<NotToString>: IntoPropValue<Option<Cow<'static, str>>>` is not satisfied
|
||||
--> $DIR/element-fail.rs:47:22
|
||||
--> $DIR/element-fail.rs:47:23
|
||||
|
|
||||
47 | html! { <a media=Some(NotToString) /> };
|
||||
| ^^^^^^^^^^^^^^^^^ the trait `IntoPropValue<Option<Cow<'static, str>>>` is not implemented for `Option<NotToString>`
|
||||
47 | html! { <a media={Some(NotToString)} /> };
|
||||
| ^^^^^^^^^^^^^^^^^ the trait `IntoPropValue<Option<Cow<'static, str>>>` is not implemented for `Option<NotToString>`
|
||||
|
|
||||
::: $WORKSPACE/packages/yew/src/virtual_dom/mod.rs
|
||||
|
|
||||
@ -238,10 +229,10 @@ error[E0277]: the trait bound `Option<NotToString>: IntoPropValue<Option<Cow<'st
|
||||
<Option<String> as IntoPropValue<Option<Cow<'static, str>>>>
|
||||
|
||||
error[E0277]: the trait bound `Option<{integer}>: IntoPropValue<Option<Cow<'static, str>>>` is not satisfied
|
||||
--> $DIR/element-fail.rs:48:21
|
||||
--> $DIR/element-fail.rs:48:22
|
||||
|
|
||||
48 | html! { <a href=Some(5) /> };
|
||||
| ^^^^^^^ the trait `IntoPropValue<Option<Cow<'static, str>>>` is not implemented for `Option<{integer}>`
|
||||
48 | html! { <a href={Some(5)} /> };
|
||||
| ^^^^^^^ the trait `IntoPropValue<Option<Cow<'static, str>>>` is not implemented for `Option<{integer}>`
|
||||
|
|
||||
::: $WORKSPACE/packages/yew/src/virtual_dom/mod.rs
|
||||
|
|
||||
@ -276,77 +267,3 @@ error[E0277]: the trait bound `{integer}: IntoPropValue<Option<yew::Callback<Mou
|
||||
<&'static str as IntoPropValue<Option<String>>>
|
||||
<&'static str as IntoPropValue<String>>
|
||||
and 11 others
|
||||
|
||||
error[E0277]: the trait bound `yew::Callback<String>: IntoPropValue<Option<yew::Callback<MouseEvent>>>` is not satisfied
|
||||
--> $DIR/element-fail.rs:52:28
|
||||
|
|
||||
52 | html! { <input onclick=Callback::from(|a: String| ()) /> };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `IntoPropValue<Option<yew::Callback<MouseEvent>>>` is not implemented for `yew::Callback<String>`
|
||||
|
|
||||
::: $WORKSPACE/packages/yew/src/html/listener/events.rs
|
||||
|
|
||||
| / impl_action! {
|
||||
3 | | onabort(name: "abort", event: Event) -> web_sys::Event => |_, event| { event }
|
||||
4 | | onauxclick(name: "auxclick", event: MouseEvent) -> web_sys::MouseEvent => |_, event| { event }
|
||||
5 | | onblur(name: "blur", event: FocusEvent) -> web_sys::FocusEvent => |_, event| { event }
|
||||
... |
|
||||
101 | | ontransitionstart(name: "transitionstart", event: TransitionEvent) -> web_sys::TransitionEvent => |_, event| { event }
|
||||
102 | | }
|
||||
| |_- required by this bound in `yew::html::onclick::Wrapper::__macro_new`
|
||||
|
||||
error[E0277]: the trait bound `Option<{integer}>: IntoPropValue<Option<yew::Callback<FocusEvent>>>` is not satisfied
|
||||
--> $DIR/element-fail.rs:53:28
|
||||
|
|
||||
53 | html! { <input onfocus=Some(5) /> };
|
||||
| ^^^^^^^ the trait `IntoPropValue<Option<yew::Callback<FocusEvent>>>` is not implemented for `Option<{integer}>`
|
||||
|
|
||||
::: $WORKSPACE/packages/yew/src/html/listener/events.rs
|
||||
|
|
||||
| / impl_action! {
|
||||
3 | | onabort(name: "abort", event: Event) -> web_sys::Event => |_, event| { event }
|
||||
4 | | onauxclick(name: "auxclick", event: MouseEvent) -> web_sys::MouseEvent => |_, event| { event }
|
||||
5 | | onblur(name: "blur", event: FocusEvent) -> web_sys::FocusEvent => |_, event| { event }
|
||||
... |
|
||||
101 | | ontransitionstart(name: "transitionstart", event: TransitionEvent) -> web_sys::TransitionEvent => |_, event| { event }
|
||||
102 | | }
|
||||
| |_- required by this bound in `yew::html::onfocus::Wrapper::__macro_new`
|
||||
|
|
||||
= help: the following implementations were found:
|
||||
<Option<&'static str> as IntoPropValue<Option<Cow<'static, str>>>>
|
||||
<Option<&'static str> as IntoPropValue<Option<String>>>
|
||||
<Option<String> as IntoPropValue<Option<Cow<'static, str>>>>
|
||||
|
||||
error[E0277]: the trait bound `(): IntoPropValue<yew::NodeRef>` is not satisfied
|
||||
--> $DIR/element-fail.rs:56:24
|
||||
|
|
||||
56 | html! { <input ref=() /> };
|
||||
| ^^ the trait `IntoPropValue<yew::NodeRef>` is not implemented for `()`
|
||||
|
|
||||
= note: required by `into_prop_value`
|
||||
|
||||
error[E0277]: the trait bound `Option<yew::NodeRef>: IntoPropValue<yew::NodeRef>` is not satisfied
|
||||
--> $DIR/element-fail.rs:57:24
|
||||
|
|
||||
57 | html! { <input ref=Some(NodeRef::default()) /> };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `IntoPropValue<yew::NodeRef>` is not implemented for `Option<yew::NodeRef>`
|
||||
|
|
||||
= help: the following implementations were found:
|
||||
<Option<&'static str> as IntoPropValue<Option<Cow<'static, str>>>>
|
||||
<Option<&'static str> as IntoPropValue<Option<String>>>
|
||||
<Option<String> as IntoPropValue<Option<Cow<'static, str>>>>
|
||||
= note: required by `into_prop_value`
|
||||
|
||||
error[E0277]: the trait bound `Cow<'static, str>: From<{integer}>` is not satisfied
|
||||
--> $DIR/element-fail.rs:71:15
|
||||
|
|
||||
71 | html! { <@{55}></@> };
|
||||
| ^^^^ the trait `From<{integer}>` is not implemented for `Cow<'static, str>`
|
||||
|
|
||||
= help: the following implementations were found:
|
||||
<Cow<'a, CStr> as From<&'a CStr>>
|
||||
<Cow<'a, CStr> as From<&'a CString>>
|
||||
<Cow<'a, CStr> as From<CString>>
|
||||
<Cow<'a, OsStr> as From<&'a OsStr>>
|
||||
and 11 others
|
||||
= note: required because of the requirements on the impl of `Into<Cow<'static, str>>` for `{integer}`
|
||||
= note: required by `into`
|
||||
|
||||
@ -13,7 +13,7 @@ fn compile_pass() {
|
||||
html! {
|
||||
<div>
|
||||
<div data-key="abc"></div>
|
||||
<div ref=parent_ref class="parent">
|
||||
<div ref={parent_ref} class="parent">
|
||||
<span class="child" value="anything"></span>
|
||||
<label for="first-name">{"First Name"}</label>
|
||||
<input type="text" id="first-name" value="placeholder" />
|
||||
@ -40,9 +40,9 @@ fn compile_pass() {
|
||||
</filter>
|
||||
</defs>
|
||||
</svg>
|
||||
<img class=classes!("avatar", "hidden") src="http://pic.com" />
|
||||
<img class={classes!("avatar", "hidden")} src="http://pic.com" />
|
||||
<img class="avatar hidden" />
|
||||
<button onclick=&onclick onclick=onclick />
|
||||
<button onclick={&onclick} onclick={onclick} />
|
||||
<a href="http://google.com" />
|
||||
<custom-tag-a>
|
||||
<custom-tag-b />
|
||||
@ -61,10 +61,10 @@ fn compile_pass() {
|
||||
}
|
||||
}/>
|
||||
|
||||
<a href=Some(Cow::Borrowed("http://google.com")) media=cow_none.clone() />
|
||||
<track kind=Some(Cow::Borrowed("subtitles")) src=cow_none.clone() />
|
||||
<track kind=Some(Cow::Borrowed("5")) mixed="works" />
|
||||
<input value=Some(Cow::Borrowed("value")) onblur=Some(Callback::from(|_| ())) />
|
||||
<a href={Some(Cow::Borrowed("http://google.com"))} media={cow_none.clone()} />
|
||||
<track kind={Some(Cow::Borrowed("subtitles"))} src={cow_none.clone()} />
|
||||
<track kind={Some(Cow::Borrowed("5"))} mixed="works" />
|
||||
<input value={Some(Cow::Borrowed("value"))} onblur={Some(Callback::from(|_| ()))} />
|
||||
</div>
|
||||
};
|
||||
|
||||
@ -75,8 +75,8 @@ fn compile_pass() {
|
||||
html! { <div>{children}</div> };
|
||||
|
||||
// handle misleading angle brackets
|
||||
html! { <div data-val=<String as Default>::default()></div> };
|
||||
html! { <div><a data-val=<String as Default>::default() /></div> };
|
||||
html! { <div data-val={<String as Default>::default()}></div> };
|
||||
html! { <div><a data-val={<String as Default>::default()} /></div> };
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
||||
@ -46,11 +46,11 @@ error: expected an expression following this equals sign
|
||||
18 | html! { <key=></> };
|
||||
| ^^
|
||||
|
||||
error: this closing tag has no corresponding opening tag
|
||||
--> $DIR/list-fail.rs:20:36
|
||||
error: the property value must be either a literal or enclosed in braces. Consider adding braces around your expression.
|
||||
--> $DIR/list-fail.rs:20:18
|
||||
|
|
||||
20 | html! { <key="key".to_string()></key> };
|
||||
| ^^^^^^
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: only a single `key` prop is allowed on a fragment
|
||||
--> $DIR/list-fail.rs:23:30
|
||||
|
||||
@ -10,7 +10,7 @@ fn main() {
|
||||
</>
|
||||
};
|
||||
::yew::html! {
|
||||
<key=::std::string::ToString::to_string("key")>
|
||||
<key={::std::string::ToString::to_string("key")}>
|
||||
</>
|
||||
};
|
||||
|
||||
|
||||
@ -27,7 +27,7 @@ fn switch(routes: &Route) -> Html {
|
||||
Route::Secure => html! {
|
||||
<div>
|
||||
<h1>{ "Secure" }</h1>
|
||||
<button onclick=onclick_callback>{ "Go Home" }</button>
|
||||
<button onclick={onclick_callback}>{ "Go Home" }</button>
|
||||
</div>
|
||||
},
|
||||
Route::NotFound => html! { <h1>{ "404" }</h1> },
|
||||
@ -36,7 +36,7 @@ fn switch(routes: &Route) -> Html {
|
||||
|
||||
// Component's `view` method
|
||||
html! {
|
||||
<Router<Route> render=Router::render(switch) />
|
||||
<Router<Route> render={Router::render(switch)} />
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@ -46,12 +46,12 @@ impl<R: Routable + Clone + PartialEq + 'static> Component for Link<R> {
|
||||
|
||||
fn view(&self) -> Html {
|
||||
html! {
|
||||
<a class=self.props.classes.clone()
|
||||
href=self.props.route.to_path()
|
||||
onclick=self.link.callback(|e: MouseEvent| {
|
||||
<a class={self.props.classes.clone()}
|
||||
href={self.props.route.to_path()}
|
||||
onclick={self.link.callback(|e: MouseEvent| {
|
||||
e.prevent_default();
|
||||
Msg::OnClick
|
||||
})
|
||||
})}
|
||||
>
|
||||
{ self.props.children.clone() }
|
||||
</a>
|
||||
|
||||
@ -22,7 +22,7 @@
|
||||
//! # #[function_component(Main)]
|
||||
//! # fn app() -> Html {
|
||||
//! html! {
|
||||
//! <Router<Route> render=Router::render(switch) />
|
||||
//! <Router<Route> render={Router::render(switch)} />
|
||||
//! }
|
||||
//! # }
|
||||
//!
|
||||
@ -33,7 +33,7 @@
|
||||
//! Route::Secure => html! {
|
||||
//! <div>
|
||||
//! <h1>{ "Secure" }</h1>
|
||||
//! <button onclick=onclick_callback>{ "Go Home" }</button>
|
||||
//! <button onclick={onclick_callback}>{ "Go Home" }</button>
|
||||
//! </div>
|
||||
//! },
|
||||
//! Route::NotFound => html! { <h1>{ "404" }</h1> },
|
||||
|
||||
@ -58,16 +58,16 @@ fn component() -> Html {
|
||||
Routes::Home => html! {
|
||||
<>
|
||||
<div id="result">{"Home"}</div>
|
||||
<a onclick=onclick>{"click me"}</a>
|
||||
<a onclick={onclick}>{"click me"}</a>
|
||||
</>
|
||||
},
|
||||
Routes::No { id } => html! { <No id=*id /> },
|
||||
Routes::No { id } => html! { <No id={*id} /> },
|
||||
Routes::NotFound => html! { <div id="result">{"404"}</div> },
|
||||
}
|
||||
});
|
||||
|
||||
html! {
|
||||
<Router<Routes> render=switch>
|
||||
<Router<Routes> render={switch}>
|
||||
</Router<Routes>>
|
||||
}
|
||||
}
|
||||
|
||||
@ -22,7 +22,7 @@ use crate::functional::{get_current_scope, use_hook};
|
||||
/// let theme = use_context::<Rc<ThemeContext>>().expect("no ctx found");
|
||||
///
|
||||
/// html! {
|
||||
/// <button style=format!("background: {}; color: {}", theme.background, theme.foreground)>
|
||||
/// <button style={format!("background: {}; color: {}", theme.background, theme.foreground)}>
|
||||
/// { "Click me" }
|
||||
/// </button>
|
||||
/// }
|
||||
|
||||
@ -31,7 +31,7 @@ struct UseEffect<Destructor> {
|
||||
/// };
|
||||
///
|
||||
/// html! {
|
||||
/// <button onclick=onclick>{ format!("Increment to {}", *counter) }</button>
|
||||
/// <button onclick={onclick}>{ format!("Increment to {}", *counter) }</button>
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@ -56,8 +56,8 @@ struct UseReducer<State> {
|
||||
/// <>
|
||||
/// <div id="result">{ counter.counter }</div>
|
||||
///
|
||||
/// <button onclick=double_onclick>{ "Double" }</button>
|
||||
/// <button onclick=square_onclick>{ "Square" }</button>
|
||||
/// <button onclick={double_onclick}>{ "Double" }</button>
|
||||
/// <button onclick={square_onclick}>{ "Square" }</button>
|
||||
/// </>
|
||||
/// }
|
||||
/// }
|
||||
@ -103,7 +103,7 @@ where
|
||||
/// <>
|
||||
/// <div id="result">{counter.counter}</div>
|
||||
///
|
||||
/// <button onclick=Callback::from(move |_| counter.dispatch(10))>{"Increment by 10"}</button>
|
||||
/// <button onclick={Callback::from(move |_| counter.dispatch(10))}>{"Increment by 10"}</button>
|
||||
/// </>
|
||||
/// }
|
||||
/// }
|
||||
|
||||
@ -41,8 +41,8 @@ use std::{cell::RefCell, rc::Rc};
|
||||
///
|
||||
/// html! {
|
||||
/// <div>
|
||||
/// <input onchange=onchange value=(*message).clone() />
|
||||
/// <button onclick=onclick>{ "Send" }</button>
|
||||
/// <input onchange={onchange} value={(*message).clone()} />
|
||||
/// <button onclick={onclick}>{ "Send" }</button>
|
||||
/// </div>
|
||||
/// }
|
||||
/// }
|
||||
|
||||
@ -25,7 +25,7 @@ struct UseState<T2> {
|
||||
///
|
||||
/// html! {
|
||||
/// <div>
|
||||
/// <button onclick=onclick>{ "Increment value" }</button>
|
||||
/// <button onclick={onclick}>{ "Increment value" }</button>
|
||||
/// <p>
|
||||
/// <b>{ "Current value: " }</b>
|
||||
/// { *counter }
|
||||
|
||||
@ -291,7 +291,7 @@ mod tests {
|
||||
self.link.send_message(msg);
|
||||
}
|
||||
self.props.lifecycle.borrow_mut().push("view".into());
|
||||
html! { <Child lifecycle=self.props.lifecycle.clone() /> }
|
||||
html! { <Child lifecycle={self.props.lifecycle.clone()} /> }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -59,7 +59,7 @@ pub type Html = VNode;
|
||||
///
|
||||
/// fn view(&self) -> Html {
|
||||
/// html! {
|
||||
/// <input ref=self.node_ref.clone() type="text" />
|
||||
/// <input ref={self.node_ref.clone()} type="text" />
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
|
||||
@ -56,7 +56,7 @@
|
||||
//! fn view(&self) -> Html {
|
||||
//! html! {
|
||||
//! <div>
|
||||
//! <button onclick=self.link.callback(|_| Msg::AddOne)>{ "+1" }</button>
|
||||
//! <button onclick={self.link.callback(|_| Msg::AddOne)}>{ "+1" }</button>
|
||||
//! <p>{ self.value }</p>
|
||||
//! </div>
|
||||
//! }
|
||||
@ -98,7 +98,7 @@ use std::{cell::Cell, panic::PanicInfo};
|
||||
/// let vec_of_classes = vec!["one-bean", "two-beans", "three-beans", "a-very-small-casserole"];
|
||||
///
|
||||
/// html! {
|
||||
/// <div class=classes!("my-container-class", conditional_class, vec_of_classes)>
|
||||
/// <div class={classes!("my-container-class", conditional_class, vec_of_classes)}>
|
||||
/// // ...
|
||||
/// </div>
|
||||
/// };
|
||||
|
||||
@ -82,8 +82,8 @@ mod test {
|
||||
fn all_key_conversions() {
|
||||
html! {
|
||||
<key="string literal">
|
||||
<img key="String".to_owned() />
|
||||
<p key=Rc::<str>::from("rc")></p>
|
||||
<img key={"String".to_owned()} />
|
||||
<p key={Rc::<str>::from("rc")}></p>
|
||||
<key='a'>
|
||||
<p key=11_usize></p>
|
||||
<p key=12_u8></p>
|
||||
|
||||
@ -320,11 +320,11 @@ mod tests {
|
||||
};
|
||||
let props_2 = props.clone();
|
||||
|
||||
check_key(html! { <Comp key=test_key.clone() /> });
|
||||
check_key(html! { <Comp key=test_key.clone() field_1=1 /> });
|
||||
check_key(html! { <Comp field_1=1 key=test_key.clone() /> });
|
||||
check_key(html! { <Comp with props key=test_key.clone() /> });
|
||||
check_key(html! { <Comp key=test_key.clone() with props_2 /> });
|
||||
check_key(html! { <Comp key={test_key.clone()} /> });
|
||||
check_key(html! { <Comp key={test_key.clone()} field_1=1 /> });
|
||||
check_key(html! { <Comp field_1=1 key={test_key.clone()} /> });
|
||||
check_key(html! { <Comp with props key={test_key.clone()} /> });
|
||||
check_key(html! { <Comp key={test_key.clone()} with props_2 /> });
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -341,11 +341,11 @@ mod tests {
|
||||
};
|
||||
let props_2 = props.clone();
|
||||
|
||||
check_node_ref(html! { <Comp ref=test_node_ref.clone() /> });
|
||||
check_node_ref(html! { <Comp ref=test_node_ref.clone() field_1=1 /> });
|
||||
check_node_ref(html! { <Comp field_1=1 ref=test_node_ref.clone() /> });
|
||||
check_node_ref(html! { <Comp with props ref=test_node_ref.clone() /> });
|
||||
check_node_ref(html! { <Comp ref=test_node_ref.clone() with props_2 /> });
|
||||
check_node_ref(html! { <Comp ref={test_node_ref.clone()} /> });
|
||||
check_node_ref(html! { <Comp ref={test_node_ref.clone()} field_1=1 /> });
|
||||
check_node_ref(html! { <Comp field_1=1 ref={test_node_ref.clone()} /> });
|
||||
check_node_ref(html! { <Comp with props ref={test_node_ref.clone()} /> });
|
||||
check_node_ref(html! { <Comp ref={test_node_ref.clone()} with props_2 /> });
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -444,7 +444,7 @@ mod tests {
|
||||
</ul>";
|
||||
|
||||
let prop_method = html! {
|
||||
<List children=children_renderer.clone()/>
|
||||
<List children={children_renderer.clone()} />
|
||||
};
|
||||
assert_eq!(get_html(prop_method, &scope, &parent), expected_html);
|
||||
|
||||
@ -481,7 +481,7 @@ mod tests {
|
||||
document().body().unwrap().append_child(&parent).unwrap();
|
||||
|
||||
let node_ref = NodeRef::default();
|
||||
let mut elem: VNode = html! { <Comp ref=node_ref.clone()></Comp> };
|
||||
let mut elem: VNode = html! { <Comp ref={node_ref.clone()}></Comp> };
|
||||
elem.apply(&scope, &parent, NodeRef::default(), None);
|
||||
let parent_node = parent.deref();
|
||||
assert_eq!(node_ref.get(), parent_node.first_child());
|
||||
|
||||
@ -790,7 +790,7 @@ mod tests {
|
||||
};
|
||||
|
||||
let d = html! {
|
||||
<div class=format!("fail{}", "")></div>
|
||||
<div class={format!("fail{}", "")}></div>
|
||||
};
|
||||
|
||||
assert_eq!(a, b);
|
||||
@ -976,7 +976,7 @@ mod tests {
|
||||
let expected = "not_changed_value";
|
||||
|
||||
// Initial state
|
||||
let mut elem = html! { <input value=expected /> };
|
||||
let mut elem = html! { <input value={expected} /> };
|
||||
elem.apply(&scope, &parent, NodeRef::default(), None);
|
||||
let vtag = if let VNode::VTag(vtag) = elem {
|
||||
vtag
|
||||
@ -990,7 +990,7 @@ mod tests {
|
||||
input.unwrap().set_value("User input");
|
||||
|
||||
let ancestor = vtag;
|
||||
let mut elem = html! { <input value=expected /> };
|
||||
let mut elem = html! { <input value={expected} /> };
|
||||
let vtag = assert_vtag_mut(&mut elem);
|
||||
|
||||
// Sync happens here
|
||||
@ -1115,7 +1115,7 @@ mod tests {
|
||||
document().body().unwrap().append_child(&parent).unwrap();
|
||||
|
||||
let node_ref = NodeRef::default();
|
||||
let mut elem: VNode = html! { <div ref=node_ref.clone()></div> };
|
||||
let mut elem: VNode = html! { <div ref={node_ref.clone()}></div> };
|
||||
assert_vtag_mut(&mut elem);
|
||||
elem.apply(&scope, &parent, NodeRef::default(), None);
|
||||
let parent_node = parent.deref();
|
||||
@ -1123,32 +1123,6 @@ mod tests {
|
||||
elem.detach(&parent);
|
||||
assert!(node_ref.get().is_none());
|
||||
}
|
||||
|
||||
/// Returns the class attribute as str reference, or "" if the attribute is not set.
|
||||
fn get_class_str(vtag: &VTag) -> &str {
|
||||
vtag.attributes
|
||||
.iter()
|
||||
.find(|(k, _)| k == &"class")
|
||||
.map(|(_, v)| AsRef::as_ref(v))
|
||||
.unwrap_or("")
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn old_class_syntax_is_still_supported() {
|
||||
let a_classes = "class-1 class-2".to_string();
|
||||
#[allow(deprecated)]
|
||||
let a = html! {
|
||||
<div class=("class-1", a_classes)></div>
|
||||
};
|
||||
|
||||
if let VNode::VTag(vtag) = a {
|
||||
assert!(get_class_str(&vtag).contains("class-1"));
|
||||
assert!(get_class_str(&vtag).contains("class-2"));
|
||||
assert!(!get_class_str(&vtag).contains("class-3"));
|
||||
} else {
|
||||
panic!("vtag expected");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@ -42,18 +42,18 @@ fn use_context_scoping_works() {
|
||||
type ExampleContextProvider = ContextProvider<ExampleContext>;
|
||||
return html! {
|
||||
<div>
|
||||
<ExampleContextProvider context=ExampleContext("wrong1".into())>
|
||||
<ExampleContextProvider context={ExampleContext("wrong1".into())}>
|
||||
<div>{"ignored"}</div>
|
||||
</ExampleContextProvider>
|
||||
<ExampleContextProvider context=ExampleContext("wrong2".into())>
|
||||
<ExampleContextProvider context=ExampleContext("correct".into())>
|
||||
<ExampleContextProvider context=ExampleContext("wrong1".into())>
|
||||
<ExampleContextProvider context={ExampleContext("wrong2".into())}>
|
||||
<ExampleContextProvider context={ExampleContext("correct".into())}>
|
||||
<ExampleContextProvider context={ExampleContext("wrong1".into())}>
|
||||
<div>{"ignored"}</div>
|
||||
</ExampleContextProvider>
|
||||
<UseContextComponentInner />
|
||||
</ExampleContextProvider>
|
||||
</ExampleContextProvider>
|
||||
<ExampleContextProvider context=ExampleContext("wrong3".into())>
|
||||
<ExampleContextProvider context={ExampleContext("wrong3".into())}>
|
||||
<div>{"ignored"}</div>
|
||||
</ExampleContextProvider>
|
||||
<ExpectNoContextComponent />
|
||||
@ -148,9 +148,9 @@ fn use_context_works_with_multiple_types() {
|
||||
|
||||
return html! {
|
||||
<div>
|
||||
<ContextAProvider context=ContextA(0)>
|
||||
<ContextBProvider context=ContextB(1)>
|
||||
<ContextAProvider context=ContextA(2)>
|
||||
<ContextAProvider context={ContextA(0)}>
|
||||
<ContextBProvider context={ContextB(1)}>
|
||||
<ContextAProvider context={ContextA(2)}>
|
||||
<Test1/>
|
||||
</ContextAProvider>
|
||||
<Test2/>
|
||||
@ -189,7 +189,7 @@ fn use_context_update_works() {
|
||||
*counter.borrow_mut() += 1;
|
||||
return html! {
|
||||
<>
|
||||
<div id=props.id.clone()>
|
||||
<div id={props.id.clone()}>
|
||||
{ format!("total: {}", counter.borrow()) }
|
||||
</div>
|
||||
{ props.children.clone() }
|
||||
@ -218,7 +218,7 @@ fn use_context_update_works() {
|
||||
return html! {
|
||||
<>
|
||||
<div>{ format!("magic: {}\n", props.magic) }</div>
|
||||
<div id=props.id.clone()>
|
||||
<div id={props.id.clone()}>
|
||||
{ format!("current: {}, total: {}", ctx.0, counter.borrow()) }
|
||||
</div>
|
||||
</>
|
||||
@ -264,10 +264,10 @@ fn use_context_update_works() {
|
||||
});
|
||||
}
|
||||
return html! {
|
||||
<MyContextProvider context=Rc::new((*ctx).clone())>
|
||||
<MyContextProvider context={Rc::new((*ctx).clone())}>
|
||||
<RenderCounter id="test-0">
|
||||
<ContextOutlet id="test-1"/>
|
||||
<ContextOutlet id="test-2" magic=magic/>
|
||||
<ContextOutlet id="test-2" magic={magic}/>
|
||||
</RenderCounter>
|
||||
</MyContextProvider>
|
||||
};
|
||||
|
||||
@ -60,7 +60,7 @@ fn use_effect_destroys_on_component_drop() {
|
||||
if *show {
|
||||
let effect_called: Rc<dyn Fn()> = { Rc::new(move || show.set(false)) };
|
||||
html! {
|
||||
<UseEffectComponent destroy_called=props.destroy_called.clone() effect_called=effect_called />
|
||||
<UseEffectComponent destroy_called={props.destroy_called.clone()} effect_called={effect_called} />
|
||||
}
|
||||
} else {
|
||||
html! {
|
||||
|
||||
@ -57,7 +57,7 @@ impl Component for MyComponent {
|
||||
fn view(&self) -> Html {
|
||||
let onclick = self.link.callback(|_| Msg::Click);
|
||||
html! {
|
||||
<button onclick=onclick>{ self.props.button_text }</button>
|
||||
<button onclick={onclick}>{ self.props.button_text }</button>
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -86,7 +86,7 @@ impl Component for MyComponent {
|
||||
|
||||
fn view(&self) -> Html {
|
||||
html! {
|
||||
<input ref=self.node_ref.clone() type="text" />
|
||||
<input ref={self.node_ref.clone()} type="text" />
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -71,7 +71,7 @@ A simple use of a callback might look something like this:
|
||||
```rust
|
||||
let onclick = self.link.callback(|_| Msg::Clicked);
|
||||
html! {
|
||||
<button onclick=onclick>{ "Click" }</button>
|
||||
<button onclick={onclick}>{ "Click" }</button>
|
||||
}
|
||||
```
|
||||
|
||||
@ -89,7 +89,7 @@ let onkeypress = self.link.batch_callback(|event| {
|
||||
});
|
||||
|
||||
html! {
|
||||
<input type="text" onkeypress=onkeypress />
|
||||
<input type="text" onkeypress={onkeypress} />
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@ -169,8 +169,8 @@ The page component can be called either with the sidebar or without:
|
||||
|
||||
// Page with sidebar
|
||||
html! {
|
||||
<Page sidebar=html_nested! {
|
||||
<Page sidebar={html_nested! {
|
||||
<PageSideBar />
|
||||
} />
|
||||
}} />
|
||||
}
|
||||
```
|
||||
|
||||
@ -19,7 +19,7 @@ self.node_ref = NodeRef::default();
|
||||
|
||||
// In view
|
||||
html! {
|
||||
<div ref=self.node_ref.clone()></div>
|
||||
<div ref={self.node_ref.clone()}></div>
|
||||
}
|
||||
|
||||
// In rendered
|
||||
|
||||
@ -11,14 +11,14 @@ theme using props:
|
||||
// root
|
||||
let theme = // ...
|
||||
html! {
|
||||
<Navbar theme=theme />
|
||||
<Navbar theme={theme} />
|
||||
}
|
||||
|
||||
// Navbar component
|
||||
html! {
|
||||
<div>
|
||||
<Title theme=theme>{ "App title" }<Title>
|
||||
<NavButton theme=theme>{ "Somewhere" }</NavButton>
|
||||
<Title theme={theme}>{ "App title" }<Title>
|
||||
<NavButton theme={theme}>{ "Somewhere" }</NavButton>
|
||||
</div>
|
||||
}
|
||||
```
|
||||
@ -63,7 +63,7 @@ impl Component for ContextDemo {
|
||||
fn view(&self) -> Html {
|
||||
let theme = self.link.context::<Theme>();
|
||||
html! {
|
||||
<button style=format!("background: {}; color: {};", theme.background, theme.foreground)>
|
||||
<button style={format!("background: {}; color: {};", theme.background, theme.foreground)}>
|
||||
{ "Click me!" }
|
||||
</button>
|
||||
}
|
||||
|
||||
@ -51,7 +51,7 @@ fn app() -> Html {
|
||||
|
||||
html! {
|
||||
<div>
|
||||
<button onclick=onclick>{ "Increment value" }</button>
|
||||
<button onclick={onclick}>{ "Increment value" }</button>
|
||||
<p>
|
||||
<b>{ "Current value: " }</b>
|
||||
{ counter }
|
||||
@ -92,6 +92,6 @@ html! {
|
||||
}
|
||||
// or
|
||||
html! {
|
||||
<MyGenericComponent<Foo> data=foo />
|
||||
<MyGenericComponent<Foo> data={foo} />
|
||||
}
|
||||
```
|
||||
|
||||
@ -26,7 +26,7 @@ fn state() -> Html {
|
||||
|
||||
html! {
|
||||
<div>
|
||||
<button onclick=onclick>{ "Increment value" }</button>
|
||||
<button onclick={onclick}>{ "Increment value" }</button>
|
||||
<p>
|
||||
<b>{ "Current value: " }</b>
|
||||
{ *counter }
|
||||
@ -70,8 +70,8 @@ fn ref_hook() -> Html {
|
||||
|
||||
html! {
|
||||
<div>
|
||||
<input onchange=onchange value=message />
|
||||
<button onclick=onclick>{ "Send" }</button>
|
||||
<input onchange={onchange} value={message} />
|
||||
<button onclick={onclick}>{ "Send" }</button>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
@ -131,8 +131,8 @@ fn reducer() -> Html {
|
||||
<>
|
||||
<div id="result">{ counter.counter }</div>
|
||||
|
||||
<button onclick=double_onclick>{ "Double" }</button>
|
||||
<button onclick=square_onclick>{ "Square" }</button>
|
||||
<button onclick={double_onclick}>{ "Double" }</button>
|
||||
<button onclick={square_onclick}>{ "Square" }</button>
|
||||
</>
|
||||
}
|
||||
}
|
||||
@ -191,7 +191,7 @@ fn effect() -> Html {
|
||||
};
|
||||
|
||||
html! {
|
||||
<button onclick=onclick>{ format!("Increment to {}", counter) }</button>
|
||||
<button onclick={onclick}>{ format!("Increment to {}", counter) }</button>
|
||||
}
|
||||
}
|
||||
```
|
||||
@ -237,7 +237,7 @@ pub fn app() -> Html {
|
||||
html! {
|
||||
// `ctx` is type `Rc<UseStateHandle<Theme>>` while we need `Theme` so we deref it
|
||||
// It derefs to `&Theme`, hence the clone
|
||||
<ContextProvider<Theme> context=(*ctx).clone()>
|
||||
<ContextProvider<Theme> context={(*ctx).clone()}>
|
||||
// Every child here and their children will have access to this context.
|
||||
<Toolbar />
|
||||
</ContextProvider<Theme>>
|
||||
@ -262,7 +262,7 @@ pub fn themed_button() -> Html {
|
||||
let theme = use_context::<Theme>().expect("no ctx found");
|
||||
|
||||
html! {
|
||||
<button style=format!("background: {}; color: {};", theme.background, theme.foreground)>
|
||||
<button style={format!("background: {}; color: {};", theme.background, theme.foreground)}>
|
||||
{ "Click me!" }
|
||||
</button>
|
||||
}
|
||||
|
||||
@ -24,7 +24,7 @@ is that every expression implements `Into<Classes>`.
|
||||
|
||||
```rust
|
||||
html! {
|
||||
<div class=classes!("container")></div>
|
||||
<div class={classes!("container")}></div>
|
||||
}
|
||||
```
|
||||
|
||||
@ -32,7 +32,7 @@ html! {
|
||||
|
||||
```rust
|
||||
html! {
|
||||
<div class=classes!("class-1", "class-2")></div>
|
||||
<div class={classes!("class-1", "class-2")}></div>
|
||||
}
|
||||
```
|
||||
|
||||
@ -42,7 +42,7 @@ html! {
|
||||
let my_classes = String::from("class-1 class-2");
|
||||
|
||||
html! {
|
||||
<div class=classes!(my_classes)></div>
|
||||
<div class={classes!(my_classes)}></div>
|
||||
}
|
||||
```
|
||||
|
||||
@ -50,7 +50,7 @@ html! {
|
||||
|
||||
```rust
|
||||
html! {
|
||||
<div class=classes!(Some("class")) />
|
||||
<div class={classes!(Some("class"))} />
|
||||
}
|
||||
```
|
||||
|
||||
@ -58,7 +58,7 @@ html! {
|
||||
|
||||
```rust
|
||||
html! {
|
||||
<div class=classes!(vec!["class-1", "class-2"])></div>
|
||||
<div class={classes!(vec!["class-1", "class-2"])}></div>
|
||||
}
|
||||
```
|
||||
|
||||
@ -68,7 +68,7 @@ html! {
|
||||
let my_classes = ["class-1", "class-2"];
|
||||
|
||||
html! {
|
||||
<div class=classes!(&my_classes)></div>
|
||||
<div class={classes!(&my_classes)}></div>
|
||||
}
|
||||
```
|
||||
|
||||
@ -104,11 +104,11 @@ impl Component for MyComponent {
|
||||
} = &self.props;
|
||||
html! {
|
||||
<div
|
||||
class=classes!(
|
||||
class={classes!(
|
||||
"my-container-class",
|
||||
fill.as_some("my-fill-class"),
|
||||
class.clone(),
|
||||
)
|
||||
)}
|
||||
>
|
||||
{ children.clone() }
|
||||
</div>
|
||||
|
||||
@ -67,7 +67,7 @@ impl Component for Container {
|
||||
|
||||
fn view(&self) -> Html {
|
||||
html! {
|
||||
<div id=self.0.id.clone()>
|
||||
<div id={self.0.id.clone()}>
|
||||
{ self.0.children.clone() }
|
||||
</div>
|
||||
}
|
||||
|
||||
@ -68,7 +68,7 @@ boolean expressions can be used:
|
||||
let no = 1 + 1 != 2;
|
||||
|
||||
html! {
|
||||
<div hidden=no>
|
||||
<div hidden={no}>
|
||||
{ "This div is NOT hidden." }
|
||||
</div>
|
||||
}
|
||||
@ -82,15 +82,13 @@ This will result in the following **HTML**:
|
||||
|
||||
## Optional attributes for HTML elements
|
||||
|
||||
Most HTML attributes can be marked as optional by placing a `?` in front of
|
||||
the `=` sign. This makes them accept the same type of value as otherwise, but
|
||||
wrapped in an `Option<T>`:
|
||||
Most HTML attributes can use optional values (Some(x) or None). This allows us to omit the attribute if the attribute is marked as optional.
|
||||
|
||||
```rust
|
||||
let maybe_id = Some("foobar");
|
||||
|
||||
html! {
|
||||
<div id?=maybe_id></div>
|
||||
<div id={maybe_id}></div>
|
||||
}
|
||||
```
|
||||
|
||||
@ -132,7 +130,7 @@ impl Component for MyComponent {
|
||||
// Create a callback from a component link to handle it in a component
|
||||
let click_callback = self.link.callback(|_: ClickEvent| Msg::Click);
|
||||
html! {
|
||||
<button onclick=click_callback>
|
||||
<button onclick={click_callback}>
|
||||
{ "Click me!" }
|
||||
</button>
|
||||
}
|
||||
@ -165,7 +163,7 @@ impl Component for MyComponent {
|
||||
// Create a callback from a worker to handle it in another context
|
||||
let click_callback = self.worker.callback(|_: ClickEvent| WorkerMsg::Process);
|
||||
html! {
|
||||
<button onclick=click_callback>
|
||||
<button onclick={click_callback}>
|
||||
{ "Click me!" }
|
||||
</button>
|
||||
}
|
||||
@ -197,7 +195,7 @@ impl Component for MyComponent {
|
||||
});
|
||||
|
||||
html! {
|
||||
<button onclick=click_callback>
|
||||
<button onclick={click_callback}>
|
||||
{ "Click me!" }
|
||||
</button>
|
||||
}
|
||||
|
||||
@ -41,7 +41,7 @@ nothing is rendered, and a message is logged to console stating that no route wa
|
||||
#[function_component(Main)]
|
||||
fn app() -> Html {
|
||||
html! {
|
||||
<Router<Route> render=Router::render(switch) />
|
||||
<Router<Route> render={Router::render(switch)} />
|
||||
}
|
||||
}
|
||||
|
||||
@ -53,7 +53,7 @@ fn switch(route: &Route) -> Html {
|
||||
html! {
|
||||
<div>
|
||||
<h1>{ "Secure" }</h1>
|
||||
<button onclick=callback>{ "Go Home" }</button>
|
||||
<button onclick={callback}>{ "Go Home" }</button>
|
||||
</div>
|
||||
}
|
||||
},
|
||||
|
||||
@ -101,7 +101,7 @@ impl Component for Model {
|
||||
fn view(&self) -> Html {
|
||||
html! {
|
||||
<div>
|
||||
<button onclick=self.link.callback(|_| Msg::AddOne)>{ "+1" }</button>
|
||||
<button onclick={self.link.callback(|_| Msg::AddOne)}>{ "+1" }</button>
|
||||
<p>{ self.value }</p>
|
||||
</div>
|
||||
}
|
||||
|
||||
@ -55,7 +55,7 @@ impl Component for MyComponent {
|
||||
fn view(&self) -> Html {
|
||||
let onclick = self.link.callback(|_| Msg::Click);
|
||||
html! {
|
||||
<button onclick=onclick>{ self.props.button_text }</button>
|
||||
<button onclick={onclick}>{ self.props.button_text }</button>
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -84,7 +84,7 @@ impl Component for MyComponent {
|
||||
|
||||
fn view(&self) -> Html {
|
||||
html! {
|
||||
<input ref=self.node_ref.clone() type="text" />
|
||||
<input ref={self.node_ref.clone()} type="text" />
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -16,7 +16,7 @@ self.node_ref = NodeRef::default();
|
||||
|
||||
// In view
|
||||
html! {
|
||||
<div ref=self.node_ref.clone()></div>
|
||||
<div ref={self.node_ref.clone()}></div>
|
||||
}
|
||||
|
||||
// In update
|
||||
|
||||
@ -111,28 +111,28 @@ html! {
|
||||
<!--Interpolated-->
|
||||
```rust
|
||||
html! {
|
||||
<div class=format!("{}-container", size)></div>
|
||||
<div class={format!("{}-container", size)}></div>
|
||||
}
|
||||
```
|
||||
|
||||
<!--Expression-->
|
||||
```rust
|
||||
html! {
|
||||
<div class=self.classes()></div>
|
||||
<div class={self.classes()}></div>
|
||||
}
|
||||
```
|
||||
|
||||
<!--Tuple-->
|
||||
```rust
|
||||
html! {
|
||||
<div class=("class-1", "class-2")></div>
|
||||
<div class={("class-1", "class-2")}></div>
|
||||
}
|
||||
```
|
||||
|
||||
<!--Vector-->
|
||||
```rust
|
||||
html! {
|
||||
<div class=vec!["class-1", "class-2"]></div>
|
||||
<div class={vec!["class-1", "class-2"]}></div>
|
||||
}
|
||||
```
|
||||
<!--END_DOCUSAURUS_CODE_TABS-->
|
||||
@ -173,7 +173,7 @@ impl Component for MyComponent {
|
||||
// Create a callback from a component link to handle it in a component
|
||||
let click_callback = self.link.callback(|_: ClickEvent| Msg::Click);
|
||||
html! {
|
||||
<button onclick=click_callback>
|
||||
<button onclick={click_callback}>
|
||||
{ "Click me!" }
|
||||
</button>
|
||||
}
|
||||
@ -206,7 +206,7 @@ impl Component for MyComponent {
|
||||
// Create a callback from a worker to handle it in another context
|
||||
let click_callback = self.worker.callback(|_: ClickEvent| WorkerMsg::Process);
|
||||
html! {
|
||||
<button onclick=click_callback>
|
||||
<button onclick={click_callback}>
|
||||
{ "Click me!" }
|
||||
</button>
|
||||
}
|
||||
@ -237,7 +237,7 @@ impl Component for MyComponent {
|
||||
});
|
||||
|
||||
html! {
|
||||
<button onclick=click_callback>
|
||||
<button onclick={click_callback}>
|
||||
{ "Click me!" }
|
||||
</button>
|
||||
}
|
||||
|
||||
@ -67,7 +67,7 @@ impl Component for Model {
|
||||
fn view(&self) -> Html {
|
||||
html! {
|
||||
<div>
|
||||
<button onclick=self.link.callback(|_| Msg::AddOne)>{ "+1" }</button>
|
||||
<button onclick={self.link.callback(|_| Msg::AddOne)}>{ "+1" }</button>
|
||||
<p>{ self.value }</p>
|
||||
</div>
|
||||
}
|
||||
|
||||
@ -51,7 +51,7 @@ impl Component for MyComponent {
|
||||
fn view(&self) -> Html {
|
||||
let onclick = self.link.callback(|_| Msg::Click);
|
||||
html! {
|
||||
<button onclick=onclick>{ self.props.button_text }</button>
|
||||
<button onclick={onclick}>{ self.props.button_text }</button>
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -77,7 +77,7 @@ impl Component for MyComponent {
|
||||
|
||||
fn view(&self) -> Html {
|
||||
html! {
|
||||
<input ref=self.node_ref.clone() type="text" />
|
||||
<input ref={self.node_ref.clone()} type="text" />
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -15,7 +15,7 @@ self.node_ref = NodeRef::default();
|
||||
|
||||
// 在 view 中
|
||||
html! {
|
||||
<div ref=self.node_ref.clone()></div>
|
||||
<div ref={self.node_ref.clone()}></div>
|
||||
}
|
||||
|
||||
// 在 update 中
|
||||
|
||||
@ -111,28 +111,28 @@ html! {
|
||||
<!--插值-->
|
||||
```rust
|
||||
html! {
|
||||
<div class=format!("{}-container", size)></div>
|
||||
<div class={format!("{}-container", size)}></div>
|
||||
}
|
||||
```
|
||||
|
||||
<!--表达式-->
|
||||
```rust
|
||||
html! {
|
||||
<div class=self.classes()></div>
|
||||
<div class={self.classes()}></div>
|
||||
}
|
||||
```
|
||||
|
||||
<!--元组-->
|
||||
```rust
|
||||
html! {
|
||||
<div class=("class-1", "class-2")></div>
|
||||
<div class={("class-1", "class-2")}></div>
|
||||
}
|
||||
```
|
||||
|
||||
<!--Vector-->
|
||||
```rust
|
||||
html! {
|
||||
<div class=vec!["class-1", "class-2"]></div>
|
||||
<div class={vec!["class-1", "class-2"]}></div>
|
||||
}
|
||||
```
|
||||
<!--END_DOCUSAURUS_CODE_TABS-->
|
||||
@ -172,7 +172,7 @@ impl Component for MyComponent {
|
||||
// 从组件 link 中创建回调来在组件中处理它
|
||||
let click_callback = self.link.callback(|_: ClickEvent| Msg::Click);
|
||||
html! {
|
||||
<button onclick=click_callback>
|
||||
<button onclick={click_callback}>
|
||||
{ "Click me!" }
|
||||
</button>
|
||||
}
|
||||
@ -204,7 +204,7 @@ impl Component for MyComponent {
|
||||
// 从 worker 中创建回调来在另一个上下文中处理它
|
||||
let click_callback = self.worker.callback(|_: ClickEvent| WorkerMsg::Process);
|
||||
html! {
|
||||
<button onclick=click_callback>
|
||||
<button onclick={click_callback}>
|
||||
{ "Click me!" }
|
||||
</button>
|
||||
}
|
||||
@ -235,7 +235,7 @@ impl Component for MyComponent {
|
||||
});
|
||||
|
||||
html! {
|
||||
<button onclick=click_callback>
|
||||
<button onclick={click_callback}>
|
||||
{ "Click me!" }
|
||||
</button>
|
||||
}
|
||||
|
||||
@ -56,7 +56,7 @@ impl Component for Model {
|
||||
fn view(&self) -> Html {
|
||||
html! {
|
||||
<div>
|
||||
<button onclick=self.link.callback(|_| Msg::AddOne)>{ "+1" }</button>
|
||||
<button onclick={self.link.callback(|_| Msg::AddOne)}>{ "+1" }</button>
|
||||
<p>{ self.value }</p>
|
||||
</div>
|
||||
}
|
||||
|
||||
@ -51,7 +51,7 @@ impl Component for MyComponent {
|
||||
fn view(&self) -> Html {
|
||||
let onclick = self.link.callback(|_| Msg::Click);
|
||||
html! {
|
||||
<button onclick=onclick>{ self.props.button_text }</button>
|
||||
<button onclick={onclick}>{ self.props.button_text }</button>
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -77,7 +77,7 @@ impl Component for MyComponent {
|
||||
|
||||
fn view(&self) -> Html {
|
||||
html! {
|
||||
<input ref=self.node_ref.clone() type="text" />
|
||||
<input ref={self.node_ref.clone()} type="text" />
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -18,7 +18,7 @@ self.node_ref = NodeRef::default();
|
||||
|
||||
// 在 view 裡
|
||||
html! {
|
||||
<div ref=self.node_ref.clone()></div>
|
||||
<div ref={self.node_ref.clone()}></div>
|
||||
}
|
||||
|
||||
// 更新
|
||||
|
||||
@ -111,28 +111,28 @@ html! {
|
||||
<!--Interpolated-->
|
||||
```rust
|
||||
html! {
|
||||
<div class=format!("{}-container", size)></div>
|
||||
<div class={format!("{}-container", size)}></div>
|
||||
}
|
||||
```
|
||||
|
||||
<!--Expression-->
|
||||
```rust
|
||||
html! {
|
||||
<div class=self.classes()></div>
|
||||
<div class={self.classes()}></div>
|
||||
}
|
||||
```
|
||||
|
||||
<!--Tuple-->
|
||||
```rust
|
||||
html! {
|
||||
<div class=("class-1", "class-2")></div>
|
||||
<div class={("class-1", "class-2")}></div>
|
||||
}
|
||||
```
|
||||
|
||||
<!--Vector-->
|
||||
```rust
|
||||
html! {
|
||||
<div class=vec!["class-1", "class-2"]></div>
|
||||
<div class={vec!["class-1", "class-2"]}></div>
|
||||
}
|
||||
```
|
||||
<!--END_DOCUSAURUS_CODE_TABS-->
|
||||
@ -172,7 +172,7 @@ impl Component for MyComponent {
|
||||
// 從一個元件連結中,建立一個 callback 並在元件中處理他
|
||||
let click_callback = self.link.callback(|_: ClickEvent| Msg::Click);
|
||||
html! {
|
||||
<button onclick=click_callback>
|
||||
<button onclick={click_callback}>
|
||||
{ "Click me!" }
|
||||
</button>
|
||||
}
|
||||
@ -204,7 +204,7 @@ impl Component for MyComponent {
|
||||
// 從一個 worker 中建立一個 callback,並在其他的 context 中處理他
|
||||
let click_callback = self.worker.callback(|_: ClickEvent| WorkerMsg::Process);
|
||||
html! {
|
||||
<button onclick=click_callback>
|
||||
<button onclick={click_callback}>
|
||||
{ "Click me!" }
|
||||
</button>
|
||||
}
|
||||
@ -235,7 +235,7 @@ impl Component for MyComponent {
|
||||
});
|
||||
|
||||
html! {
|
||||
<button onclick=click_callback>
|
||||
<button onclick={click_callback}>
|
||||
{ "Click me!" }
|
||||
</button>
|
||||
}
|
||||
|
||||
@ -64,7 +64,7 @@ impl Component for Model {
|
||||
fn view(&self) -> Html {
|
||||
html! {
|
||||
<div>
|
||||
<button onclick=self.link.callback(|_| Msg::AddOne)>{ "+1" }</button>
|
||||
<button onclick={self.link.callback(|_| Msg::AddOne)}>{ "+1" }</button>
|
||||
<p>{ self.value }</p>
|
||||
</div>
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user