npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@alizharb/bootstrap-multiselect

v1.0.3

Published

Bootstrap-styled multiselect dropdown with search, tags, remote data and themes.

Readme

azh-select

azh-select logo Advanced Select Component for Bootstrap 5

License: MIT Latest Version Total Downloads Bootstrap JavaScript File Size No Dependencies

Powerful, lightweight, and highly customizable select component with search, tags, remote API loading, custom templates, and full dark mode support.

📖 Documentation🚀 Quick Start💡 Examples🎨 Themes🔧 API Reference

📚 Demo & Full Documentation

🔗 Live Demo & Complete Documentation


✨ Features

🎯 Core Features

  • Single & Multiple Selection - Standard and multi-select modes
  • Real-time Search - Filter options as you type
  • Tag Creation - Users can create new options dynamically
  • Clear Button - Easy reset functionality
  • Keyboard Navigation - Full accessibility support
  • Form Integration - Works seamlessly with HTML forms

🚀 Advanced Features

  • Remote API Loading - Load data from REST endpoints
  • Custom Templates - Rich HTML templates for options
  • Dark/Light Themes - Bootstrap 5 theme integration
  • Event System - Comprehensive event callbacks
  • Responsive Design - Mobile-first responsive layout
  • Performance Optimized - Efficient rendering for large datasets

🎯 Quick Start

Installation

Option 1: Direct Download

<!-- CSS -->
<link rel="stylesheet" href="path/to/dist/css/azh-select.min.css" />
<!-- JavaScript -->
<script src="path/to/dist/js/azh-select.min.js"></script>

Option 2: CDN

<!-- CSS -->
<link
  rel="stylesheet"
  href="https://cdn.jsdelivr.net/npm/@alizharb/[email protected]/dist/css/azh-select.min.css"
/>
<!-- JavaScript -->
<script src="https://cdn.jsdelivr.net/npm/@alizharb/[email protected]/dist/js/azh-select.min.js"></script>

Option 3: NPM

npm install @alizharb/bootstrap-multiselect

Requirements

  • Bootstrap 5.0+ (Required for styling)
  • Modern Browser with ES6+ support

Basic Usage

<!-- Include Bootstrap 5 -->
<link
  href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"
  rel="stylesheet"
/>

<!-- Include azh-select -->
<link rel="stylesheet" href="azh-select.min.css" />
<script src="azh-select.min.js"></script>

<!-- Create your select -->
<select class="form-select azh-select" data-placeholder="Choose an option">
  <option value="1">Option 1</option>
  <option value="2">Option 2</option>
  <option value="3">Option 3</option>
</select>

<!-- Initialize -->
<script>
  document.addEventListener("DOMContentLoaded", () => {
    azhSelect.init(".azh-select");
  });
</script>

💡 Examples

Basic Select

<select class="form-select azh-select" data-placeholder="Select an option">
  <option value="apple">🍎 Apple</option>
  <option value="banana">🍌 Banana</option>
  <option value="cherry">🍒 Cherry</option>
</select>

Searchable Multi-Select

<select
  class="form-select azh-select"
  multiple
  data-search="true"
  data-placeholder="Search and select multiple"
>
  <option value="html">HTML</option>
  <option value="css">CSS</option>
  <option value="js">JavaScript</option>
  <option value="php">PHP</option>
</select>

Tags (Creatable Options)

<select
  class="form-select azh-select"
  multiple
  data-search="true"
  data-tags="true"
  data-placeholder="Type to create new tags"
>
  <option value="frontend">Frontend</option>
  <option value="backend">Backend</option>
  <option value="fullstack">Full Stack</option>
</select>

Remote API Integration

<select
  class="form-select azh-select"
  data-remote="true"
  data-endpoint="https://api.example.com/users"
  data-search="true"
  data-value-field="id"
  data-label-field="name"
  data-placeholder="Search users..."
></select>

Custom Templates

azhSelect.init("#customSelect", {
  templateOption: (opt) => {
    return `<i class="bi bi-star text-warning me-2"></i>${opt.label}`;
  },
  templateValue: (opt) => {
    return `<span class="badge bg-primary">${opt.label}</span>`;
  },
});

⚙️ Configuration

Data Attributes

| Attribute | Type | Default | Description | | ------------------ | ------- | ------------- | --------------------------------- | | data-search | Boolean | false | Enable search functionality | | data-clear | Boolean | false | Show clear button | | data-tags | Boolean | false | Allow tag creation | | data-remote | Boolean | false | Enable remote data loading | | data-endpoint | String | null | API endpoint URL | | data-placeholder | String | "Select..." | Placeholder text | | data-max | Number | null | Maximum selections (multi-select) | | data-value-field | String | "id" | API response value field | | data-label-field | String | "name" | API response label field | | data-min-query | Number | 1 | Minimum chars for remote search | | data-delay | Number | 300 | Remote search delay (ms) | | data-preload | Boolean | false | Preload remote data | | data-bs-theme | String | "light" | Bootstrap theme |

JavaScript Options

azhSelect.init(".azh-select", {
  // Template functions
  templateOption: (opt) => opt.label,
  templateValue: (opt) => opt.label,

  // Internationalization
  i18n: {
    placeholder: "Select...",
    clear: "Clear",
    noResults: "No results found",
  },
});

🎨 Theming

azh-select fully supports Bootstrap 5's theme system with automatic dark/light mode detection.

Theme Integration

<!-- Global theme -->
<html data-bs-theme="dark">
  <!-- Individual select theme -->
  <select class="form-select azh-select" data-bs-theme="dark">
    <option value="1">Dark themed option</option>
  </select>
</html>

Custom Styling

.my-custom-select {
  --azh-bg: #f0f8ff;
  --azh-border: #4682b4;
  --azh-text: #1e3a8a;
  --azh-hover-bg: rgba(70, 130, 180, 0.1);
  --azh-selected-bg: rgba(70, 130, 180, 0.2);
}

Dynamic Theme Switching

function toggleTheme() {
  const html = document.documentElement;
  const currentTheme = html.getAttribute("data-bs-theme");
  const newTheme = currentTheme === "dark" ? "light" : "dark";
  html.setAttribute("data-bs-theme", newTheme);
}

🔧 API Reference

Global Methods

| Method | Parameters | Description | | ------------------------ | ------------------- | -------------------------- | | azhSelect.init() | selector, options | Initialize select elements | | azhSelect.get() | selector | Get instance by selector | | azhSelect.destroy() | selector | Destroy specific instance | | azhSelect.destroyAll() | - | Destroy all instances |

Instance Methods

| Method | Description | | ----------- | --------------------- | | clear() | Clear all selections | | open() | Open dropdown | | close() | Close dropdown | | toggle() | Toggle dropdown state | | destroy() | Destroy instance |

Events

| Event | Trigger | Detail | | ------------------- | -------------------- | ---------------------------- | | azh:change | Selection changes | {instance} | | azh:clear | Clear button clicked | {instance} | | azh:open | Dropdown opens | {instance} | | azh:close | Dropdown closes | {instance} | | azh:optionCreated | New tag created | {instance, value} | | azh:remoteLoaded | Remote data loaded | {instance, query, options} | | azh:error | Remote API error | {instance, error} |

Event Usage

document
  .querySelector("#mySelect")
  .addEventListener("azh:change", function (e) {
    console.log("Selection changed:", e.target.value);
  });

document
  .querySelector("#mySelect")
  .addEventListener("azh:optionCreated", function (e) {
    console.log("New tag created:", e.detail.value);
  });

🌐 Remote API Integration

Server Requirements

Your API should return JSON arrays:

[
  { "id": 1, "name": "John Doe", "email": "[email protected]" },
  { "id": 2, "name": "Jane Smith", "email": "[email protected]" }
]

Search Implementation

When search is enabled, queries are sent as URL parameters:

GET /api/users?q=john

Server Examples

Route::get('/api/users', function (Request $request) {
    $query = $request->get('q');

    return User::when($query, function ($q) use ($query) {
        return $q->where('name', 'LIKE', "%{$query}%")
                ->orWhere('email', 'LIKE', "%{$query}%");
    })
    ->select('id', 'name', 'email')
    ->limit(50)
    ->get();
});
app.get("/api/users", (req, res) => {
  const query = req.query.q;
  let sql = "SELECT id, name, email FROM users";
  let params = [];

  if (query) {
    sql += " WHERE name LIKE ? OR email LIKE ?";
    params = [`%${query}%`, `%${query}%`];
  }

  db.query(sql + " LIMIT 50", params, (err, results) => {
    if (err) return res.status(500).json({ error: err.message });
    res.json(results);
  });
});
from django.http import JsonResponse
from django.db.models import Q

def users_api(request):
    query = request.GET.get('q', '')
    users = User.objects.all()

    if query:
        users = users.filter(
            Q(name__icontains=query) | Q(email__icontains=query)
        )

    return JsonResponse(
        list(users.values('id', 'name', 'email')[:50]),
        safe=False
    )

🔧 Advanced Usage

Form Integration

<form class="needs-validation" novalidate>
  <div class="mb-3">
    <label class="form-label">Required Field</label>
    <select class="form-select azh-select" name="category" required>
      <option value="">Select...</option>
      <option value="tech">Technology</option>
      <option value="design">Design</option>
    </select>
    <div class="invalid-feedback">Please select a category.</div>
  </div>
  <button type="submit" class="btn btn-primary">Submit</button>
</form>

Framework Integration

import React, { useEffect, useRef } from "react";
import azhSelect from "azh-select";

function AzhSelectComponent({ options, value, onChange }) {
  const selectRef = useRef();

  useEffect(() => {
    azhSelect.init(selectRef.current);
    selectRef.current.addEventListener("azh:change", onChange);

    return () => azhSelect.destroy(selectRef.current);
  }, []);

  return (
    <select ref={selectRef} className="form-select azh-select">
      {options.map((opt) => (
        <option key={opt.value} value={opt.value}>
          {opt.label}
        </option>
      ))}
    </select>
  );
}
<template>
  <select ref="select" class="form-select azh-select" v-model="value">
    <option v-for="option in options" :key="option.value" :value="option.value">
      {{ option.label }}
    </option>
  </select>
</template>

<script>
import azhSelect from "azh-select";

export default {
  props: ["options", "value"],
  mounted() {
    azhSelect.init(this.$refs.select);
    this.$refs.select.addEventListener("azh:change", () => {
      this.$emit("input", this.$refs.select.value);
    });
  },
  beforeDestroy() {
    azhSelect.destroy(this.$refs.select);
  },
};
</script>

🛠️ Development

Building from Source

# Clone the repository
git clone https://github.com/alizharb/azh-select.git
cd azh-select

# Install dependencies
npm install

# Build for production
npm run build

# Development with live reload
npm run dev

# Run tests
npm test

Project Structure

azh-select/
├── dist/
│   ├── js/
│   │   ├── azh-select.js
│   │   └── azh-select.min.js
│   ├── css/
│   │   ├── azh-select.css
│   │   └── azh-select.min.css
│   ├── scss/
│   │   └── azh-select.scss
│   └── less/
│       └── azh-select.less
├── types/       # TypeScript typings

🧪 Browser Support

| Browser | Version | Notes | | ------- | ------- | --------------- | | Chrome | 60+ | ✅ Full support | | Firefox | 55+ | ✅ Full support | | Safari | 12+ | ✅ Full support | | Edge | 79+ | ✅ Full support | | IE | ❌ | Not supported |

Feature Support

  • CSS Custom Properties: All supported browsers
  • Fetch API: All supported browsers
  • Custom Events: All supported browsers
  • ES6 Classes: All supported browsers

🤝 Contributing

We welcome contributions! Please see our Contributing Guide for details.

Ways to Contribute

  • 🐛 Bug Reports - Found an issue? Let us know!
  • 💡 Feature Requests - Have an idea? Share it!
  • 📝 Documentation - Help improve our docs
  • 🔧 Code - Submit pull requests
  • 🧪 Testing - Help test new features

Development Setup

  1. Fork the repository
  2. Create a feature branch: git checkout -b feature-name
  3. Make your changes and test thoroughly
  4. Submit a pull request with a clear description

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.


🙏 Acknowledgments

  • Bootstrap Team - For the amazing CSS framework
  • Contributors - Everyone who has contributed to this project
  • Community - For feedback, bug reports, and feature suggestions

📞 Support


⭐ Star this repo if you find it useful!

Made with ❤️ by Ali Harb