# Registering Custom Component

# ▶️ Step 1.

Navigate to the 📁 HTML/js/components folder and create a new file named MyCustomComponent.js.

# ▶️ Step 2.

Open the created file and add the following code skeleton:

export default class MyCustomComponent extends BaseComponent {
  constructor({
    name,
    loadInnerComponents,
    parent,
    element
  }) {
    super({
      name,
      loadInnerComponents,
      parent,
      element,
      // Component default options
      defaults: {

      },
      // Component inner elements
      innerElements: {

      }
    });
  }
}

# ▶️ Step 3.

Open the template's main frontend file 📄 HTML/js/app.js and register your component in the 🔧 app.components object as follows:





 
 
 




window.app = {
  ...
  components: {
    ...
    'MyCustomComponent': {
      dependencies: [], // leave this empty for now
      file: './components/MyCustomComponent.js' // path to your file
    }
  }
}

# ▶️ Step 4.

Open your component JS file 📄 HTML/js/components/MyCustomComponent.js and extend its code base with the following example:

export default class MyCustomComponent extends BaseComponent {
  constructor({
    name,
    loadInnerComponents,
    parent,
    element
  }) {
    super({
      name,
      loadInnerComponents,
      parent,
      element,
      // Component default options
      defaults: {
        myOption1: true,
        myOption2: 'stringValue',
        myAnotherOption: 55,
      },
      // Component inner elements
      innerElements: {
        myInnerElementsSet: '.js-my-custom-component__element',
        myAnotherInnerElementsSet: '.js-my-custom-component__another-element',
      }
    });

    // Setup the component and run the init() function
    this.setup();
  }

  // Component code goes here
  init() {
    // You can organize it in functions
    this.myFunction1();
    this.myFunction2();
    this.myFunction3();
  }

  // This is the place to clean up your component work if needed (optional)
  destroy() {
    console.log('This code will be automatically executed before the next page is loaded in an AJAX transition');
  }

  // Prepare your animation scene here (set initial values, positions, transforms, etc)
  prepareAnimation() {
    return new Promise((resolve) => {
      const tl = gsap.timeline({
        onComplete: () => resolve(true)
      });

      if (this.elements.myInnerElementsSet.length) {
        tl.set(this.elements.myInnerElementsSet, {
          y: '100%',
          autoAlpha: 0
        });
      }
    });
  }

  // Put the actual on-scroll animation scene there
  getRevealAnimation() {
    const tl = gsap.timeline({
      paused: true
    });

    if (this.elements.myInnerElementsSet.length) {
      tl.to(this.elements.myInnerElementsSet, {
        y: '0%',
        autoAlpha: 1,
        stagger: 0.2
      });
    }

    return tl;
  }

  myFunction1() {
    console.log('1. Custom code here...');
  }

  myFunction2() {
    console.log('2. Custom code there...');
  }

  myFunction3() {
    console.log('3. Third function call');

    // Use "this.options" to get a parsed object of the component options
    console.log(`Here goes the value of "myOption1": ${this.options.myOption1}`);
    console.log(`Here goes the value of "myOption2": ${this.options.myOption2}`);
    console.log(`Here goes the value of "myAnotherOption": ${this.options.myAnotherOption}`);

    // Use "this.element" for the reference of the component HTML element
    console.log(`This is the component container HTML element`);
    console.log(this.element);
    console.log(`=================`);

    // Use "this.elements" for the references of the inner component elements
    console.log(`Component inner elements:`);
    console.log(this.elements);
    console.log(`=================`);

    // Use "this.innerSelectors" to get the original selectors of inner elements
    console.log(`Here are selectors of the inner elements:`);
    console.log(this.innerSelectors);
    console.log(`=================`);
  }
}

# ▶️ Step 5.

Open any HTML page of the template and add the custom component code to the main page container.













 
 
 








<main
  class="page-wrapper bg-gray-3"
  id="page-wrapper"
  data-barba="container"
  data-arts-color-theme="dark"
  >
  <div
    class="page-wrapper__content"
    id="page-wrapper__content"
    >
    <div
      class="d-flex js-my-custom-component"
      data-arts-component-name="MyCustomComponent"
      data-arts-component-options="{}"
      data-arts-os-animation="true"
      >
      <div class="w-100 js-my-custom-component__element">Inner element 1</div>
      <div class="w-100 js-my-custom-component__element">Inner element 2</div>
      <div class="w-100 js-my-custom-component__element">Inner element 3</div>
    </div>
  </div>
</main>

You can have multiple instances of your component as well. Each instance can have its own options and inner elements. Note the custom options set on the 2nd instance in the example below. Those will override the component defaults using a "deep-merge" algorithm.



























 






<main
  class="page-wrapper bg-gray-3"
  id="page-wrapper"
  data-barba="container"
  data-arts-color-theme="dark"
  >
  <div
    class="page-wrapper__content"
    id="page-wrapper__content"
    >
    <!-- Instance #1 -->
    <div
      class="d-flex js-my-custom-component"
      data-arts-component-name="MyCustomComponent"
      data-arts-component-options="{}"
      data-arts-os-animation="true"
      >
      <div class="w-100 js-my-custom-component__element">Inner element 1</div>
      <div class="w-100 js-my-custom-component__element">Inner element 2</div>
      <div class="w-100 js-my-custom-component__element">Inner element 3</div>
    </div>

    <!-- Instance #2 (no animation, different options) -->
    <div
      class="d-flex js-my-custom-component"
      data-arts-component-name="MyCustomComponent"
      data-arts-component-options="{myOption1: false, myOption2: 'different string'}"
      >
      <div class="w-100 js-my-custom-component__element">Inner element of the 2nd instance 1</div>
    </div>
  </div>
</main>