Props System

Master the flow of data between components. PawaJS uses a unique getter-based prop system to ensure fine-grained reactivity.

The Getter Pattern

Unlike many frameworks that pass raw values, PawaJS passes props as functions (getters). This is the secret to its "Continuity" model—by passing a function, the child component can execute it at any time to retrieve the latest reactive value without requiring the whole component to re-render.

Important: Always call your props as functions in your template or logic, e.g. propName(). The only exception is the children prop, which is a raw string.

Prop Naming & Conversions

PawaJS automatically normalizes attribute names to JavaScript-friendly prop names. This ensures consistency with standard DOM property naming conventions.

CamelCase Conversion
Hyphenated attributes are converted to camelCase.
  • :on-change-valueonChangeValue
  • :user-iduserId
  • :is-loadingisLoading
Special Mappings
Reserved HTML attributes are mapped to properties.
  • classclassName
  • defaultdefaultValue

Reactive vs. Static Props

Reactive Binding (:prop)

Use a colon prefix to pass reactive state, numbers, or complex JS expressions.

html

                 
<user-profile 
  :age="25" 
  :name="user.name.value" 
/> 

        

Since it evaluates as JavaScript, you can also define inline functions:

html

                 
<custom-list 
  :on-item-click="(id) => console.log('Item selected:', id)" 
></custom-list> 

        

Static Binding (prop)

Omit the colon to pass fixed strings. These are still received as getters returning that string.

html

                 
<user-profile 
  theme="dark" 
  label="Account" 
/> 

        

Event Handlers: Directive vs. Prop

PawaJS supports two distinct ways of handling events. Choosing the correct one is important.

on-click="myFunction()" (Event Directive)

Attaches a native DOM event listener. The expression is evaluated when the event fires. If the child component does not declare an onClick prop, the handler still works via the rest / fallthrough mechanism (--).

:on-click="myFunction" (Function Prop)

Passes the function reference as a prop named onClick. The child component must declare and call this prop itself.

Key Distinction: Use the on- directive (no colon) when you want a native DOM listener or when you want the event to fall through via --. Use the :on- form only when the child component explicitly accepts and invokes the prop.

Attribute Fallthrough (--)

When you pass standard HTML attributes like class, style, or id to a component, they are captured as "rest props". You can direct these attributes to a specific element inside your component using the double-dash -- syntax.

Implementation
html

                 
<!-- Parent Template -->
<custom-button class="btn-primary" id="login-btn">
  Login
</custom-button> 

        
js

                 
// Component Definition
const CustomButton = ({ children }) => {
  return html`
    <div class="wrapper">
       <!-- Attributes from parent will land on this button -->
       <button -->${children}</button>
    </div>`;
}; 

        

The forwardProps Hook

If you need to programmatically manage which props are considered "rest attributes" or if you want to forward them to another PawaJS component or a native DOM element, use the forwardProps hook for more control.

js

                 
import { forwardProps, html } from 'pawajs';

const InputGroup = ({children,...props}) => {
  // Explicitly forward the incoming props to the next level
  forwardProps(props);

  return html`
    <div class="group">
      <label>User Input</label>
      <!-- 'props' are now available for the next component's fallthrough -->
      <custom-input --></custom-input>
    </div>`;
}; 

        

Type Safety & Validation

PawaJS includes a runtime validation utility to ensure your components receive the data they expect.

js

                 
import { useValidateComponent } from 'pawajs';

const MyComponent = ({ title }) => { ... };

useValidateComponent(MyComponent, {
  title: {
    type: String,
    strict: true, // Required prop
    default: 'Default Title'
  },
  count: {
    type: Number,
    err: 'The count prop must be a valid integer'
  }
});