GithubHelp home page GithubHelp logo

lukethacoder / custom-elements Goto Github PK

View Code? Open in Web Editor NEW

This project forked from gbj/custom-elements

1.0 1.0 0.0 48 KB

A CustomElement trait to create Rust/WASM Web Components/Custom Elements easily without writing any JavaScript.

JavaScript 10.45% Rust 89.55%

custom-elements's Introduction

crates.io docs.rs

A framework-agnostic CustomElement trait to create Rust/WASM Web Components/Custom Elements easily without writing any JavaScript.

Overview

The Web Components standard creates a browser feature that allows you to create reusable components, called Custom Elements. (People often use the label “Web Components” when they mean Custom Elements in particular; the Web Components standard also includes Shadow DOM and HTML Templates.)

While web_sys exposes the browser’s CustomElementRegistry interface, it can be hard to use. Creating a Custom Element requires calling customElements.define() and passing it an ES2015 class that extends HTMLElement, which is not currently possible to do directly from Rust.

This crate provides a CustomElement trait that, when implemented, allows you to encapsulate any Rust structure as a reusable web component without writing any JavaScript. In theory it should be usable with any Rust front-end framework; the examples directory contains examples for Yew and for a vanilla Rust/WASM component.

impl CustomElement for MyWebComponent {
  fn inject_children(&mut self, this: &HtmlElement) {
      inject_style(&this, "p { color: green; }");
      let node = self.view();
      this.append_child(&node).unwrap_throw();
  }

  fn observed_attributes() -> &'static [&'static str] {
      &["name"]
  }

  fn attribute_changed_callback(
      &mut self,
      _this: &HtmlElement,
      name: String,
      _old_value: Option<String>,
      new_value: Option<String>,
  ) {
      if name == "name" {
          /* do something... */
      }
  }

  fn connected_callback(&mut self, _this: &HtmlElement) {
      log("connected");
  }

  fn disconnected_callback(&mut self, _this: &HtmlElement) {
      log("disconnected");
  }

  fn adopted_callback(&mut self, _this: &HtmlElement) {
      log("adopted");
  }
}

#[wasm_bindgen]
pub fn define_custom_elements() {
    MyWebComponent::define("my-component");
}

Shadow DOM

By default, these custom elements use the Shadow DOM (in “open” mode) to encapsulate the styles and content of the element. You can override that choice simply by implementing the shadow method and returning false:

fn shadow() -> bool {
    false
}

Lifecycle Methods

You can implement each of the custom element’s lifecycle callbacks. Each of the callbacks is passed both the component for which the trait is being implemented, and the HtmlElement of the custom element.

fn connected_callback(&mut self, this: &HtmlElement) {
    log("connected");
}

fn disconnected_callback(&mut self, this: &HtmlElement) {
    log("disconnected");
}

fn adopted_callback(&mut self, this: &HtmlElement) {
    log("adopted");
}

fn attribute_changed_callback(
    &mut self,
    this: &HtmlElement,
    name: String,
    old_value: Option<String>,
    new_value: Option<String>,
) {
    if name == "name" {
        // do something
    }
}

Using Rust Frameworks

The minimum needed to implement CustomElement is some way to inject children into the custom element. It’s also generally helpful to have it respond to changes in its attributes via the attribute_changed_callback. Depending on the framework, these may be more or less difficult to accomplish; in particular, for Elm-inspired frameworks you may need to create a wrapper that owns some way of updating the app’s state.

See the Yew example for an example of how to work with a framework’s API.

Customized built-in elements

Custom elements can either be autonomous (<my-component></my-component>) or customized built-in elements (<p is="my-paragraph-component"></p>). This crate offers support for creating customized built-in elements via the superclass` method.

Resources

This is a fairly minimal wrapper for the Custom Elements API. The following MDN sources should give you more than enough information to start creating custom elements:

Running the Examples

The examples use wasm-pack and a simple Python server. You should be able to run them with a simple

./build.sh && ./runserver

custom-elements's People

Contributors

gbj avatar

Stargazers

 avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.