Conversation
Codecov Report❌ Patch coverage is
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
4824f19 to
e6b2f3d
Compare
c55425b to
c7ba160
Compare
| /// Creates a new `HtmlTag` instance for a datalist element. | ||
| /// | ||
| /// # Examples | ||
| /// ``` | ||
| /// use cot::html::HtmlTag; | ||
| /// let data_list = HtmlTag::data_list(vec!["Option 1", "Option 2"], "my-datalist"); | ||
| /// let rendered = data_list.render(); | ||
| /// ``` |
There was a problem hiding this comment.
nit:
| /// Creates a new `HtmlTag` instance for a datalist element. | |
| /// | |
| /// # Examples | |
| /// ``` | |
| /// use cot::html::HtmlTag; | |
| /// let data_list = HtmlTag::data_list(vec!["Option 1", "Option 2"], "my-datalist"); | |
| /// let rendered = data_list.render(); | |
| /// ``` | |
| /// Creates a new `HtmlTag` instance for a [datalist] element. | |
| /// | |
| /// # Examples | |
| /// ``` | |
| /// use cot::html::HtmlTag; | |
| /// let data_list = HtmlTag::data_list(vec!["Option 1", "Option 2"], "my-datalist"); | |
| /// let rendered = data_list.render(); | |
| /// ``` | |
| /// | |
| /// [datalist]: https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/datalist |
| let l = item.as_ref(); | ||
| let mut option = HtmlTag::new("option"); | ||
| option.attr("value", l); | ||
| option.push_str(l); |
There was a problem hiding this comment.
As I look in the MDN docs and HTML standard, option only needs to have the content in the value field, not s a children.
| option.push_str(l); |
| /// let rendered = data_list.render(); | ||
| /// ``` | ||
| #[must_use] | ||
| pub fn data_list<I, S>(list: I, id: &str) -> Self |
There was a problem hiding this comment.
I'm not sure if we should force providing id in the constructor, maybe getting rid of it and expecting users to do .attr("id", id") is enough?
| pub autocapitalize: Option<AutoCapitalize>, | ||
| /// Corresponds to the [`AutoComplete`] attribute in the HTML input element. | ||
| pub autocomplete: Option<AutoComplete>, |
There was a problem hiding this comment.
Those are global attributes so they apply to all HTML elements, maybe we should add some macro that will add them to every HTML element struct we create or via composition? What do you think @m4tx? 🤔
| if let Some(min_length) = self.custom_options.min_length { | ||
| tag.attr("minlength", min_length.to_string()); | ||
| } | ||
|
|
||
| if let Some(placeholder) = &self.custom_options.placeholder { | ||
| tag.attr("placeholder", placeholder); | ||
| } | ||
| if let Some(readonly) = self.custom_options.readonly | ||
| && readonly | ||
| { | ||
| tag.bool_attr("readonly"); | ||
| } | ||
| if let Some(autocomplete) = &self.custom_options.autocomplete { | ||
| tag.attr("autocomplete", autocomplete.to_string()); | ||
| } | ||
|
|
||
| if let Some(size) = self.custom_options.size { | ||
| tag.attr("size", size.to_string()); | ||
| } | ||
|
|
||
| if let Some(dir) = &self.custom_options.dir { | ||
| tag.attr("dir", dir.as_str()); | ||
| } | ||
|
|
||
| if let Some(dirname) = &self.custom_options.dirname { | ||
| tag.attr("dirname", dirname); | ||
| } | ||
|
|
||
| if let Some(list) = &self.custom_options.list { | ||
| let list_id = format!("__{}_datalist", self.id()); | ||
| tag.attr("list", &list_id); | ||
|
|
||
| let data_list = HtmlTag::data_list(list.clone(), &list_id); | ||
| tag.push_tag(data_list); | ||
| } | ||
|
|
There was a problem hiding this comment.
nit: can you sort them in the same order as field declaration in the struct?
|
|
||
| if let Some(min_length) = self.custom_options.min_length { | ||
| tag.attr("minlength", min_length.to_string()); | ||
| } | ||
| if let Some(placeholder) = &self.custom_options.placeholder { | ||
| tag.attr("placeholder", placeholder); | ||
| } | ||
| if let Some(readonly) = self.custom_options.readonly | ||
| && readonly | ||
| { | ||
| tag.bool_attr("readonly"); | ||
| } | ||
| if let Some(autocomplete) = &self.custom_options.autocomplete { | ||
| tag.attr("autocomplete", autocomplete.to_string()); | ||
| } | ||
|
|
||
| if let Some(size) = self.custom_options.size { | ||
| tag.attr("size", size.to_string()); | ||
| } | ||
|
|
There was a problem hiding this comment.
nit: can you sort them in the same order as field declaration in the struct?
| if let Some(placeholder) = &self.custom_options.placeholder { | ||
| tag.attr("placeholder", placeholder); | ||
| } | ||
| if let Some(readonly) = self.custom_options.readonly | ||
| && readonly | ||
| { | ||
| tag.bool_attr("readonly"); | ||
| } | ||
| if let Some(autocomplete) = &self.custom_options.autocomplete { | ||
| tag.attr("autocomplete", autocomplete.to_string()); | ||
| } | ||
|
|
||
| if let Some(size) = self.custom_options.size { | ||
| tag.attr("size", size.to_string()); | ||
| } | ||
|
|
||
| if let Some(dir) = &self.custom_options.dir { | ||
| tag.attr("dir", dir.as_str()); | ||
| } | ||
|
|
||
| if let Some(dirname) = &self.custom_options.dirname { | ||
| tag.attr("dirname", dirname); | ||
| } | ||
|
|
||
| if let Some(list) = &self.custom_options.list { | ||
| let list_id = format!("__{}_datalist", self.id()); | ||
| tag.attr("list", &list_id); | ||
|
|
||
| data_list = Some(HtmlTag::data_list(list.clone(), &list_id)); | ||
| } | ||
|
|
||
| if let Some(value) = &self.value { | ||
| tag.attr("value", value); | ||
| } | ||
|
|
||
| if let Some(data_list) = data_list { | ||
| let mut wrapper = HtmlTag::new("div"); | ||
| wrapper | ||
| .attr("id", format!("__{}_datalist_wrapper", self.id())) | ||
| .push_tag(tag) | ||
| .push_tag(data_list); | ||
| return write!(f, "{}", wrapper.render()); | ||
| } |
There was a problem hiding this comment.
nit: can you sort them in the same order as field declaration in the struct?
| impl HtmlSafe for EmailField {} | ||
|
|
||
| impl_form_field!(IntegerField, IntegerFieldOptions, "an integer", T: Integer); | ||
| impl_form_field!(IntegerField, IntegerFieldOptions, "an integer", T: Integer + Display); |
There was a problem hiding this comment.
Why was it needed here and below for float field?
| if let Some(max_length) = self.custom_options.max_length { | ||
| tag.attr("maxlength", max_length.to_string()); | ||
| } | ||
| if let Some(min_length) = self.custom_options.min_length { | ||
| tag.attr("minlength", min_length.to_string()); | ||
| } | ||
| if let Some(placeholder) = &self.custom_options.placeholder { | ||
| tag.attr("placeholder", placeholder); | ||
| } | ||
| if let Some(readonly) = self.custom_options.readonly | ||
| && readonly | ||
| { | ||
| tag.bool_attr("readonly"); | ||
| } | ||
| if let Some(autocomplete) = &self.custom_options.autocomplete { | ||
| tag.attr("autocomplete", autocomplete.to_string()); | ||
| } | ||
|
|
||
| if let Some(size) = self.custom_options.size { | ||
| tag.attr("size", size.to_string()); | ||
| } | ||
|
|
||
| if let Some(dir) = &self.custom_options.dir { | ||
| tag.attr("dir", dir.as_str()); | ||
| } | ||
|
|
||
| if let Some(dirname) = &self.custom_options.dirname { | ||
| tag.attr("dirname", dirname); | ||
| } | ||
|
|
||
| if let Some(list) = &self.custom_options.list { | ||
| let list_id = format!("__{}_datalist", self.id()); | ||
| tag.attr("list", &list_id); | ||
|
|
||
| let data_list = HtmlTag::data_list(list, &list_id); | ||
| tag.push_tag(data_list); | ||
| } |
There was a problem hiding this comment.
nit: can you sort them in the same order as field declaration in the struct?
| /// | ||
| /// [`list`]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#list | ||
| #[derive(Debug, Clone, Default)] | ||
| pub struct List(Vec<String>); |
There was a problem hiding this comment.
The linked docs about list attribute for <input> claim that:
The value given to the list attribute should be the id of a element located in the same document.
I understand that your approach was of simplicity, but I think we should first and foremost support the spec and then add conveniences for the users.
I'd say that new should take the id of datalist by default. Or even better, take a datalist struct, but now it's generic HtmlTag, which doesn't make it that much better.
Then, we can provide a convenience constructor, let's say from_list, that has the existing functionality.
This PR adds more form attributes to various HTML elements in cot