The Principal Dev – Masterclass for Tech Leads

The Principal Dev – Masterclass for Tech LeadsNov 27-28

Join

MiniJS

Mini is a library extension for HTML which lets you add interactivity to your app without needing a full blown frontend framework.

The Idea

Setting State

State are variables that changes the UI or the DOM that uses it when they get updated.

Note: Only non-objects are supported for reactive state.

Setting Initial State

You can set the initial state of the variables using vanilla JS:

<script type="text/javascript">
  firstName = 'Tony'
  lastName = 'Ennis'
</script>

Syncing the DOM with your state

These are the following dynamic attributes that you can use to sync the DOM with your state:

<script type="text/javascript">
  firstName = 'Tony'
</script>

<input type="text" :change="firstName = this.value" />

<!-- The innerText of this paragraph changes based on the firstName variable -->
<p :text="firstName"></p>

Triggering DOM Updates / Re-renders

A DOM update or a re-render happens when the state variable is re-assigned in dynamic events.

<input type="text" :change="firstName = this.value" />
<!-- the re-assignment of firstName will trigger DOM updates that uses that variable -->

When re-assignment happens in dynamic attributes, it will not trigger a re-render to avoid infinite loops.

<p :text="firstName = 'Tony'"></p>
<!-- the re-assignment of firstName will not trigger DOM updates -->

Special Variables

There are special variables that you can use inside dynamic attributes and events:

Dynamic Attributes

Besides :value, :class, and :text, you can also make any attribute dynamic by renaming it from attribute to :attribute. Values set to dynamic attributes are evaluated as JavaScript:

<script>
  pStyle = 'color: red'
</script>

<p :style="pStyle">My style is changing</p>
<button
  :click="if (pStyle === 'color: red')
						pStyle = 'color: blue';
					else
						pStyle = 'color: red'"
>
  Toggle Style
</button>

Classes

You can make your class names reactive by using the :class attribute:

<script type="text/javascript">
  isActive = false
</script>

<button :click="isActive = !isActive" :class="isActive ? 'active' : ''">
  Click Me
</button>

Setting the Default Classes

To set default classes, you can use the class attribute:

<div class="hidden" :class="shouldShow ? 'visible' : 'hidden'"></div>

Setting Multiple Reactive Classes

To set multiple reactive classes, you can use the :class attribute:

  1. Use multiple ternary operators enclosed in parentheses:
<div
  :class="(selectedTab === 'When' ? 'bg-white shadow-lg' : 'hover:bg-gray-300')
          (whenSelectedTab === 'Dates' ? 'hidden' : '')"
></div>
  1. Use if-else statements:
<div
  :class="if (selectedTab === 'When') {
            return 'bg-white shadow-lg'
          } else {
            return 'hover:bg-gray-300'
          }

          if (whenSelectedTab === 'Dates') {
            return 'hidden'
          } else {
            return ''
          }"
></div>

Events

You can create, use, and update state variables inside DOM events.

In events, you can get the current event using the event variable:

<button :click="console.log(event)">Click Me</button>

Native Events

All native events are supported. You can use them like this:

<button :click="console.log('click')">Click Me</button>

You can access the current element in the event via this:

<button :click="this.classList.toggle('active')">Click Me</button>

<input :change="this.value = this.value.toUpperCase()" />

Custom Events

These are the events added in by MiniJS:

Keyboard Events

For keyboard events, you can listen to them using :keyup, :keydown, and :keypress:

<input type="text" :keyup="console.log(event)" />

Key Modifiers

You can also use key modifiers to listen to specific keys. Modifiers are appended to the event name using a dot:

<input
  type="text"
  :keyup.up="console.log('keyup.up')"
  :keydown.enter="console.log('keydown.enter')"
/>

You can chain multiple key modifiers together:

<input type="text" :keydown.slash.k="console.log('keydown.slash.k')" />

For key values that have multiple words like BracketLeft, except for arrow keys, kebab case is used:

<input
  type="text"
  :keydown.bracket-left="console.log('keydown.bracket-left')"
/>

The following are the available key modifiers:

Type Key Value Modifier Usage
Digits (0-9) Digit1, Digit2 1, 2 :keyup.1, :keyup.2
Letters (A-Z, a-z) KeyA, KeyB a, b :keyup.a, :keyup.b
Numpad (0-9) Numpad1, Numpad2 1, 2 :keyup.1, :keyup.2
Arrow Keys (up, down, left, right) ArrowLeft, ArrowRight left, right :keyup.left, :keyup.right
Meta (left, right) Meta, MetaLeft, MetaRight meta, meta-left, meta-right :keyup.meta, :keyup.meta-left, :keyup.meta-right
Alt (left, right) Alt, AltLeft, AltRight alt, alt-left, alt-right :keyup.alt, :keyup.alt-left, :keyup.alt-right
Control (left, right) Control, ControlLeft, ControlRight ctrl, ctrl-left, ctrl-right :keyup.ctrl, :keyup.ctrl-left, :keyup.ctrl-right
Shift (left, right) Shift, ShiftLeft, ShiftRight shift, shift-left, shift-right :keyup.shift, :keyup.shift-left, :keyup.shift-right
Symbols (., /, =, etc.) Period, BracketLeft, Slash period, bracket-left, slash :keyup.period, :keyup.bracket-left, :keyup.slash

Note: If you don't know the "name" of a symbol key, you can use the console.log(event.code) to see the key value. Example for the "Enter" key: :keyup="console.log(event.code)" will log "Enter". So you can use :keyup.enter to listen to the "Enter" key.


Statements

Each Statement

The :each statement is used to loop through an array and render a template for each item.

<script>
  items = ['Tag 1', 'Tag 2', 'Tag 3', 'Tag 4']
</script>

<ul :each="item in items">
  <li :text="item"></li>
</ul>

<ul :each="item, index in items">
  <li :text=" `The item is ${item}. The index is ${index}` "></li>
</ul>

You can also use complex variables for the :each statement:

<script>
  items = [
    { name: 'Tag 1', id: 1 },
    { name: 'Tag 2', id: 2 },
    { name: 'Tag 3', id: 3 },
    { name: 'Tag 4', id: 4 },
  ]
</script>

<ul :each="item in items">
  <li :text="item.name"></li>
</ul>

Note: Each item variables are read-only, which means you can't re-assign them like:

<ul :each="item in items">
  <li :load="item = 'new value'" :text="item"></li>
</ul>

Variables

Variables saved in Local Storage

Appending $ to the variable name will save the variable in the local storage:

<script type="text/javascript">
  $firstName = 'Tony'
</script>

<input type="text" :change="$firstName = this.value" />

Note: Currently, this is only available for globally declared variables.

Variable Scoping

Global Variables

Whenever you create a variable, it will automatically be added to the global scope. This means that you can access it anywhere in your code.

<script type="text/javascript">
  firstName = 'Tony'
</script>

<button :click="console.log(firstName)">Click Me</button>

Local Variables

To use variables only in a current event, you can create a local variable using const, and let:

<button
  :click="const time = new Date();
          window.alert(time.toLocaleTimeString())"
>
  Click Me
</button>

Element Variables

If you want to use the variable across an element's attributes and events, you can use el.:

<script>
  items = ['Tag 1', 'Tag 2', 'Tag 3', 'Tag 4']
</script>

<button
  :load="el.selectedItem = items.pop()"
  :click="el.selectedItem = items.pop()"
  :text="`Last Item: ${el.selectedItem}`"
>
  Click Me
</button>

Like the example above, :load can be used to set the initial value of the variable.

Scope Variables

Adding a :scope attribute to an element will allow you to access its variables from its children using scope. variables.

<!-- Scope Element -->
<div id="accordion" class="accordion" :scope>
  <!-- Children Elements -->
  <section
    class="grid transition-all border-gray-300 border border-b-0 rounded hover:bg-gray-100"
  >
    <button
      :click="scope.activeSection = 'about'"
      class="cursor-pointer font-bold p-4"
    >
      About Us
    </button>
    <div
      class="p-4 pt-2 overflow-hidden hidden"
      :class="scope.activeSection =='about' ? 'block' : 'hidden'"
    >
      Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy
      eirmod.
    </div>
  </section>

  <section
    class="grid transition-all border-gray-300 border border-b-0 rounded hover:bg-gray-100"
  >
    <button
      :click="scope.activeSection = 'contact'"
      class="cursor-pointer font-bold p-4"
    >
      Contact Us
    </button>
    <div
      class="p-4 pt-2 overflow-hidden"
      :class="scope.activeSection =='contact' ? 'block' : 'hidden'"
    >
      Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy
      eirmod.
    </div>
  </section>

  <section
    class="grid transition-all border-gray-300 border rounded hover:bg-gray-100"
    :class="scope.activeSection =='team' ? 'active' : ''"
  >
    <button
      :click="scope.activeSection = 'team'"
      class="cursor-pointer font-bold p-4"
    >
      Team 3
    </button>
    <div
      class="p-4 pt-2 overflow-hidden"
      :class="scope.activeSection =='team' ? 'block' : 'hidden'"
    >
      Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy
      eirmod.
    </div>
  </section>
</div>

You can set the default value of the scope variables in the :scope directive:

<div id="accordion" class="accordion" :scope="activeSection = 'about'">
  <!-- ... -->
</div>

Variable Methods

MiniJS added some commonly-used custom methods to variables.

Array

Here are the custom array methods which are available for you to use:

Contributors


Jen

💻 🚇 📖

tonyennis145

📖 💻

Joeylene

🚇 💻 📖 ⚠️

Jen

📖 💻

Installation

To setup MiniJS in your local machine, you can do the following:

  1. Clone the repository.
  2. Run yarn to install dependencies.
  3. Run yarn build to create the dist folder -> output for MiniJS.
  4. Run yarn dev to run the demo page locally.
  5. Run yarn build-watch on another terminal to build the code whenever the Mini.js code changes.
  6. Run yarn test to run the tests.

Join libs.tech

...and unlock some superpowers

GitHub

We won't share your data with anyone else.