Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow users to declare custom html elements #259

Open
5 tasks
simon-bourne opened this issue Mar 22, 2021 · 4 comments
Open
5 tasks

Allow users to declare custom html elements #259

simon-bourne opened this issue Mar 22, 2021 · 4 comments

Comments

@simon-bourne
Copy link
Contributor

This would allow moxie-dom users to use third party web components. It looks like making html_element public would be a good direction to support this.

@simon-bourne
Copy link
Contributor Author

Straw Man Plan

html_element!

I don't think there's much that would need to be added to html_element! to support declaring custom html elements. We just need a way of declaring custom events. For example:

html_element! {
    <fast-tree-item>

    categories { Flow }

    children {
        categories {
            Flow
        }
    }

    attributes {
        /// Is this tree item expanded?
        expanded(bool)
        /// Is this tree item selected?
        selected(bool)
    }

    custom_events {
        selected-change
        expanded-change
    }
}

We should probably tweak the syntax to make it more Rust-like if it's going to be made public. expanded(bool) should probably become expanded: bool for example.

Defining Web Components

The plan is just to declare custom html elements, so moxie-dom users can use third party web components. This section is just an exploration of what defining custom html elements might look like, so we can see how it fits in with declaring them.

See here for instructions on using custom elements in Javascript. In summary, we call customElements.define('my-custom-element', MyCustomElement) to register the element. MyCustomElement has a static observedAttributes method that returns an array of attribute names. MyCustomElement also has some lifecycle methods, connectedCallback, attributeChangedCallback, disconnectedCallback and adoptedCallback.

We've already got the element name, attribute and event names from html_element. So we could add an optional define MyCustomElement to html_element!, then, given these traits:

pub trait CustomHtmlElement {
    fn name() -> &'static str;
    fn observed_attributes() -> ...;
    fn attribute_changed(self, ...);
}

pub trait OwnedHtmlElement {
    fn connected(self, ...);
    fn disconnected(self, ...);
    fn adopted(self, ...);
}

html_element! could generate:

impl CustomHtmlElement for MyCustomElement {
    fn name() { ... }
    fn observed_attributes() -> ... { ... }
    fn attribute_changed(self, ...) {
        // Dispatch to named, typed methods on `self`
    }
}

impl MyCustomElement {
    fn dispatch_my_event(self, detail) { ... }
    fn dispatch_my_other_event(self, detail) { ... }
    ...
}

Then a user would define attribute update methods and implement OwnedHtmlElement.

@simon-bourne simon-bourne changed the title Allow users to define custom html elements Allow users to declare custom html elements Mar 25, 2021
@anp
Copy link
Owner

anp commented Apr 4, 2021

@anp: you mentioned that html_element had some warts that you'd like to consider before making it public. I found issue #240. Was there anything else?

Nothing comes to mind right now, although I think your point about how to write expected(bool as expected: bool is a good one.

declaring custom events

Would the user need to define their own event types for these, would we generate opaque event type wrappers for them?

I like the basic direction of using a trait to define a custom element within moxie, and I agree we don't need to sort it out to be able to make use of existing web components :D.

@simon-bourne
Copy link
Contributor Author

@anp: you mentioned that html_element had some warts that you'd like to consider before making it public. I found issue #240. Was there anything else?

Nothing comes to mind right now, although I think your point about how to write expected(bool as expected: bool is a good one.

I was also thinking commas between elements, but no strong preference either way.

declaring custom events

Would the user need to define their own event types for these, would we generate opaque event type wrappers for them?

I was thinking the user would supply their own event type with a constructor that accepted a Javascript CustomEvent. We need to give access to the event target as that's defined by the web component, but this allows the user to make the Javascript event opaque downstream. For example, if the event was selected-event, the user would define something like:

#[derive(Constructor)]
struct SelectedEvent{
    // User can decide how they want to represent their event
}

impl SelectedEvent {
    pub fn new(event: web_sys::CustomEvent) { ... }

    // User can provide whatever methods they want.
}

and we'd generate a call to SelectedEvent::new.

@anp
Copy link
Owner

anp commented Apr 25, 2021

What about requiring SelectedEvent: From<web_sys::CustomEvent>?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants