CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-materialize-css

Material Design CSS framework with interactive JavaScript components for building responsive web applications

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

forms.mddocs/

Form Components

Enhanced form controls and input components including text fields, selects, date/time pickers, autocomplete, file inputs, and form validation with Material Design styling and JavaScript functionality.

Capabilities

Text Fields and Textarea

Enhanced text inputs with floating labels, validation, and character counting.

/**
 * Global form utilities available on M object
 */
declare const M: {
  /** Update all text field labels (call after dynamic content changes) */
  updateTextFields(): void;
  
  /** Validate individual form field */
  validate_field(field: Element): boolean;
  
  /** Auto-resize textarea to fit content */
  textareaAutoResize(textarea: Element): void;
};

HTML Structure and CSS Classes:

<!-- Basic text input -->
<div class="input-field">
  <input id="first_name" type="text" class="validate">
  <label for="first_name">First Name</label>
</div>

<!-- Textarea with character counter -->
<div class="input-field">
  <textarea id="textarea1" class="materialize-textarea" data-length="120"></textarea>
  <label for="textarea1">Message</label>
</div>

<!-- Input with icon -->
<div class="input-field">
  <i class="material-icons prefix">account_circle</i>
  <input id="icon_prefix" type="text" class="validate">
  <label for="icon_prefix">Username</label>
</div>

<!-- Input with validation -->
<div class="input-field">
  <input id="email" type="email" class="validate">
  <label for="email">Email</label>
  <span class="helper-text" data-error="Invalid email" data-success="Valid email">Enter your email</span>
</div>

Character Counter

Automatic character counting for text inputs and textareas.

/**
 * Character counter component
 * @param el - Input or textarea element with data-length attribute
 * @param options - Configuration options (currently empty)
 */
class CharacterCounter {
  constructor(el: Element, options?: {});
  
  static init(els: Element | NodeList, options?: {}): CharacterCounter | CharacterCounter[];
  static getInstance(el: Element): CharacterCounter;
  static get defaults(): {};
  
  /** Update character count display */
  updateCounter(): void;
  
  destroy(): void;
}

Usage Examples:

<!-- Character counter via data attribute -->
<div class="input-field">
  <input id="input_text" type="text" data-length="10">
  <label for="input_text">Input text</label>
</div>

<div class="input-field">
  <textarea id="textarea2" class="materialize-textarea" data-length="120"></textarea>
  <label for="textarea2">Textarea</label>
</div>
// Initialize character counters
const elems = document.querySelectorAll('input[data-length], textarea[data-length]');
M.CharacterCounter.init(elems);

// Manual update after programmatic changes
const instance = M.CharacterCounter.getInstance(document.getElementById('input_text'));
instance.updateCounter();

Select Dropdown

Enhanced select dropdowns with search functionality and custom styling.

/**
 * Form select component (enhanced dropdown select)
 * @param el - Select element
 * @param options - Configuration options
 */
class FormSelect {
  constructor(el: Element, options?: FormSelectOptions);
  
  static init(els: Element | NodeList, options?: FormSelectOptions): FormSelect | FormSelect[];
  static getInstance(el: Element): FormSelect;
  static get defaults(): FormSelectOptions;
  
  /** Get array of selected values */
  getSelectedValues(): string[];
  
  destroy(): void;
}

interface FormSelectOptions {
  /** Additional CSS classes for dropdown */
  classes?: string;
  
  /** Options to pass to underlying Dropdown component */
  dropdownOptions?: {
    alignment?: 'left' | 'right';
    autoFocus?: boolean;
    constrainWidth?: boolean;
    container?: Element;
    coverTrigger?: boolean;
    closeOnClick?: boolean;
    hover?: boolean;
    inDuration?: number;
    outDuration?: number;
  };
}

Usage Examples:

<!-- Basic select -->
<div class="input-field">
  <select>
    <option value="" disabled selected>Choose your option</option>
    <option value="1">Option 1</option>
    <option value="2">Option 2</option>
    <option value="3">Option 3</option>
  </select>
  <label>Materialize Select</label>
</div>

<!-- Multiple select -->
<div class="input-field">
  <select multiple>
    <option value="" disabled selected>Choose your options</option>
    <option value="1">Option 1</option>
    <option value="2">Option 2</option>
    <option value="3">Option 3</option>
  </select>
  <label>Multiple Select</label>
</div>

<!-- Select with icons -->
<div class="input-field">
  <select>
    <option value="" disabled selected>Choose your option</option>
    <option value="1" data-icon="images/sample-1.jpg" class="left circle">Option 1</option>
    <option value="2" data-icon="images/sample-2.jpg" class="left circle">Option 2</option>
  </select>
  <label>Select with Icons</label>
</div>
// Initialize select dropdowns
const elems = document.querySelectorAll('select');
const instances = M.FormSelect.init(elems);

// Get selected values
const instance = M.FormSelect.getInstance(document.querySelector('select'));
const selectedValues = instance.getSelectedValues();
console.log('Selected:', selectedValues);

Datepicker

Date selection component with calendar interface and internationalization support.

/**
 * Datepicker component
 * @param el - Input element for date selection
 * @param options - Configuration options
 */
class Datepicker {
  constructor(el: Element, options?: DatepickerOptions);
  
  static init(els: Element | NodeList, options?: DatepickerOptions): Datepicker | Datepicker[];
  static getInstance(el: Element): Datepicker;
  static get defaults(): DatepickerOptions;
  
  /** Open datepicker */
  open(): void;
  
  /** Close datepicker */
  close(): void;
  
  /** Set selected date programmatically */
  setDate(date?: Date): void;
  
  /** Update input value from selected date */
  setInputValue(): void;
  
  /** Navigate to specific date */
  gotoDate(date: Date): void;
  
  destroy(): void;
}

interface DatepickerOptions {
  /** Automatically close picker when date is selected */
  autoClose?: boolean; // default: false
  
  /** Date format for display */
  format?: string; // default: 'mmm dd, yyyy'
  
  /** Custom parse function for date strings */
  parse?: (value: string, format: string) => Date;
  
  /** Default date to show */
  defaultDate?: Date;
  
  /** Set default date as selected */
  setDefaultDate?: boolean; // default: false
  
  /** Disable weekends */
  disableWeekends?: boolean; // default: false
  
  /** Custom function to disable specific dates */
  disableDayFn?: (date: Date) => boolean;
  
  /** First day of week (0 = Sunday) */
  firstDay?: number; // default: 0
  
  /** Minimum selectable date */
  minDate?: Date;
  
  /** Maximum selectable date */
  maxDate?: Date;
  
  /** Year range for year selector */
  yearRange?: number; // default: 10
  
  /** Show clear button */
  showClearBtn?: boolean; // default: false
  
  /** Show month after year in title */
  showMonthAfterYear?: boolean; // default: false
  
  /** Show days of adjacent months */
  showDaysInNextAndPreviousMonths?: boolean; // default: false
  
  /** Container for datepicker modal */
  container?: Element;
  
  /** Internationalization options */
  i18n?: {
    cancel?: string;
    clear?: string;
    done?: string;
    previousMonth?: string;
    nextMonth?: string;
    months?: string[];
    monthsShort?: string[];
    weekdays?: string[];
    weekdaysShort?: string[];
    weekdaysAbbrev?: string[];
  };
  
  /** Callbacks */
  onSelect?: (date: Date) => void;
  onOpen?: () => void;
  onClose?: () => void;
  onDraw?: () => void;
}

Usage Examples:

<!-- Basic datepicker -->
<div class="input-field">
  <input type="text" class="datepicker">
  <label for="birthdate">Birthdate</label>
</div>
// Initialize datepickers
const elems = document.querySelectorAll('.datepicker');
const instances = M.Datepicker.init(elems, {
  format: 'yyyy-mm-dd',
  autoClose: true,
  minDate: new Date(2020, 0, 1), // January 1, 2020
  maxDate: new Date(2025, 11, 31), // December 31, 2025
  onSelect: (date) => console.log('Date selected:', date)
});

// Programmatic date setting
const instance = M.Datepicker.getInstance(document.querySelector('.datepicker'));
instance.setDate(new Date(2023, 5, 15)); // June 15, 2023

Timepicker

Time selection component with clock interface and customizable options.

/**
 * Timepicker component
 * @param el - Input element for time selection
 * @param options - Configuration options
 */
class Timepicker {
  constructor(el: Element, options?: TimepickerOptions);
  
  static init(els: Element | NodeList, options?: TimepickerOptions): Timepicker | Timepicker[];
  static getInstance(el: Element): Timepicker;
  static get defaults(): TimepickerOptions;
  
  /** Open timepicker */
  open(): void;
  
  /** Close timepicker */
  close(): void;
  
  destroy(): void;
}

interface TimepickerOptions {
  /** Animation duration */
  duration?: number; // default: 350
  
  /** Container selector */
  container?: string; // default: 'body'
  
  /** Show clear button */
  showClearBtn?: boolean; // default: false
  
  /** Default time */
  defaultTime?: string; // default: 'now'
  
  /** Minutes from now as default time */
  fromNow?: number; // default: 0
  
  /** Internationalization */
  i18n?: {
    cancel?: string;
    clear?: string;
    done?: string;
  };
  
  /** Auto close on time selection */
  autoClose?: boolean; // default: false
  
  /** Use 12-hour format */
  twelveHour?: boolean; // default: true
  
  /** Vibrate on touch (mobile) */
  vibrate?: boolean; // default: true
  
  /** Callbacks */
  onOpenStart?: () => void;
  onOpenEnd?: () => void;
  onCloseStart?: () => void;
  onCloseEnd?: () => void;
  onSelect?: (hour: number, minute: number) => void;
}

Usage Examples:

<!-- Basic timepicker -->
<div class="input-field">
  <input type="text" class="timepicker">
  <label for="appt-time">Appointment Time</label>
</div>
// Initialize timepickers
const elems = document.querySelectorAll('.timepicker');
const instances = M.Timepicker.init(elems, {
  twelveHour: false, // 24-hour format
  autoClose: true,
  onSelect: (hour, minute) => console.log(`Time: ${hour}:${minute}`)
});

Autocomplete

Autocomplete input with customizable data sources and filtering.

/**
 * Autocomplete component
 * @param el - Input element
 * @param options - Configuration options
 */
class Autocomplete {
  constructor(el: Element, options?: AutocompleteOptions);
  
  static init(els: Element | NodeList, options?: AutocompleteOptions): Autocomplete | Autocomplete[];
  static getInstance(el: Element): Autocomplete;
  static get defaults(): AutocompleteOptions;
  
  /** Select option programmatically */
  selectOption(el: Element): void;
  
  /** Open autocomplete dropdown */
  open(): void;
  
  /** Close autocomplete dropdown */
  close(): void;
  
  /** Update autocomplete data */
  updateData(data: { [key: string]: string | null }): void;
  
  destroy(): void;
}

interface AutocompleteOptions {
  /** Data object for autocomplete */
  data?: { [key: string]: string | null }; // key: display text, value: image URL or null
  
  /** Limit number of results */
  limit?: number; // default: Infinity
  
  /** Callback when autocomplete selection is made */
  onAutocomplete?: (text: string) => void;
  
  /** Minimum characters before autocomplete activates */
  minLength?: number; // default: 1
  
  /** Custom sort function for results */
  sortFunction?: (a: string, b: string, inputString: string) => number;
}

Usage Examples:

<!-- Autocomplete input -->
<div class="input-field">
  <input type="text" id="autocomplete-input" class="autocomplete">
  <label for="autocomplete-input">Autocomplete</label>
</div>
// Initialize autocomplete
const elems = document.querySelectorAll('.autocomplete');
const instances = M.Autocomplete.init(elems, {
  data: {
    "Apple": null,
    "Microsoft": null,
    "Google": "https://placehold.it/250x250",
    "Amazon": null,
    "Facebook": null
  },
  limit: 5,
  onAutocomplete: (val) => console.log('Autocomplete value:', val)
});

// Update data dynamically
const instance = M.Autocomplete.getInstance(document.getElementById('autocomplete-input'));
instance.updateData({
  "New Item 1": null,
  "New Item 2": "https://example.com/image.jpg"
});

Chips

Chip input component for tags and multi-value inputs.

/**
 * Chips component for tag input
 * @param el - Chips container element
 * @param options - Configuration options
 */
class Chips {
  constructor(el: Element, options?: ChipsOptions);
  
  static init(els: Element | NodeList, options?: ChipsOptions): Chips | Chips[];
  static getInstance(el: Element): Chips;
  static get defaults(): ChipsOptions;
  
  /** Get chips data */
  getData(): ChipData[];
  
  /** Add chip */
  addChip(chip: ChipData): void;
  
  /** Delete chip by index */
  deleteChip(chipIndex: number): void;
  
  /** Select chip by index */
  selectChip(chipIndex: number): void;
  
  destroy(): void;
}

interface ChipData {
  tag: string;
  image?: string;
}

interface ChipsOptions {
  /** Initial chip data */
  data?: ChipData[];
  
  /** Placeholder text */
  placeholder?: string;
  
  /** Secondary placeholder text */
  secondaryPlaceholder?: string;
  
  /** Autocomplete options */
  autocompleteOptions?: AutocompleteOptions;
  
  /** Maximum number of chips */
  limit?: number; // default: Infinity
  
  /** Callbacks */
  onChipAdd?: (element: Element, chip: Element) => void;
  onChipSelect?: (element: Element, chip: Element) => void;
  onChipDelete?: (element: Element, chip: Element) => void;
}

Usage Examples:

<!-- Basic chips -->
<div class="chips"></div>

<!-- Chips with initial data -->
<div class="chips chips-initial"></div>

<!-- Chips with placeholder -->
<div class="chips chips-placeholder"></div>
// Initialize chips
const elems = document.querySelectorAll('.chips');
M.Chips.init(elems);

// Chips with initial data
const chipInitial = document.querySelector('.chips-initial');
M.Chips.init(chipInitial, {
  data: [
    { tag: 'Apple' },
    { tag: 'Microsoft' },
    { tag: 'Google' }
  ]
});

// Chips with placeholder and autocomplete
const chipPlaceholder = document.querySelector('.chips-placeholder');
M.Chips.init(chipPlaceholder, {
  placeholder: 'Enter a tag',
  secondaryPlaceholder: '+Tag',
  autocompleteOptions: {
    data: {
      'JavaScript': null,
      'TypeScript': null,
      'Python': null,
      'Java': null
    }
  }
});

// Get chip data
const instance = M.Chips.getInstance(chipPlaceholder);
const chipData = instance.getData();
console.log('Current chips:', chipData);

Range Slider

Enhanced range input with Material Design styling.

/**
 * Range slider component
 * @param el - Input range element
 * @param options - Configuration options (currently empty)
 */
class Range {
  constructor(el: Element, options?: {});
  
  static init(els: Element | NodeList, options?: {}): Range | Range[];
  static getInstance(el: Element): Range;
  static get defaults(): {};
  
  destroy(): void;
}

Usage Examples:

<!-- Basic range slider -->
<form action="#">
  <p class="range-field">
    <input type="range" id="test5" min="0" max="100" />
  </p>
</form>
// Initialize range sliders
const elems = document.querySelectorAll('input[type=range]');
M.Range.init(elems);

Form Validation

CSS Validation Classes

/* Validation states */
.valid {
  /* Applied to valid inputs */
  border-bottom: 1px solid #4CAF50;
  box-shadow: 0 1px 0 0 #4CAF50;
}

.invalid {
  /* Applied to invalid inputs */
  border-bottom: 1px solid #F44336;
  box-shadow: 0 1px 0 0 #F44336;
}

/* Helper text */
.helper-text {
  /* Helper text styling */
  font-size: 0.8rem;
  color: rgba(0,0,0,0.54);
}

.helper-text.invalid {
  /* Error message styling */
  color: #F44336;
}

JavaScript Validation

// Manual field validation
const emailField = document.getElementById('email');
const isValid = M.validate_field(emailField);

// Update all text fields (useful after AJAX content)
M.updateTextFields();

// Custom validation function
function validateForm(form) {
  let isValid = true;
  const inputs = form.querySelectorAll('input[type="text"], input[type="email"]');
  
  inputs.forEach(input => {
    if (!M.validate_field(input)) {
      isValid = false;
    }
  });
  
  return isValid;
}

Common Form Patterns

Dynamic Form Updates

// After adding form elements dynamically
M.updateTextFields();
M.FormSelect.init(document.querySelectorAll('select'));
M.CharacterCounter.init(document.querySelectorAll('input[data-length], textarea[data-length]'));

// Reinitialize specific components
const newDatepickers = document.querySelectorAll('.datepicker:not([data-select-id])');
M.Datepicker.init(newDatepickers);

Form Submission Handling

document.getElementById('myForm').addEventListener('submit', function(e) {
  e.preventDefault();
  
  // Validate all fields
  const inputs = this.querySelectorAll('input.validate');
  let allValid = true;
  
  inputs.forEach(input => {
    if (!M.validate_field(input)) {
      allValid = false;
    }
  });
  
  if (allValid) {
    // Process form submission
    const formData = new FormData(this);
    console.log('Form is valid, submitting...', formData);
  } else {
    M.toast({html: 'Please fix validation errors'});
  }
});

docs

css-framework.md

forms.md

index.md

interactive.md

layout.md

media.md

navigation.md

utilities.md

tile.json