Dylan  Iqbal

Dylan Iqbal

1620265693

Bootstrap 5 has Officially Released

Bootstrap 5 has officially landed! After three alphas, three betas, and several months of hard work, we’re shipping the first stable release of our new major version. It’s been a wild ride made possible by our maintainers and the amazing community that uses and contributes to Bootstrap. Thanks to all who have helped us get here!

Keep reading for details on what’s new compared to v4 and what’s coming for subsequent releases. Want to get right to it? Head to the new v5 docs or fly by the seat of your pants and just npm i bootstrap.


In this post:

  • New logo!
  • New offcanvas component
  • New accordion
  • New and updated forms
    * Checks and radios
    * Floating labels
    * New file input
    * Simplified layout
  • RTL is here!
  • Overhauled utilities
    * New utilities API
    * New utilities
    * Logical properties for spacing utilities
  • New snippet examples
  • Grid and layout
  • More component updates
  • Improved customizing
  • Dart Sass
  • Browser support
  • JavaScript
  • Migration guide
  • Get the release
  • What’s next
  • v5.1.0 preview
  • Support the team

New logo!

New Bootstrap logo

One of the biggest changes with v5 came with our redesigned logo and updated docs design. Inspired by the work we’ve done in Bootstrap Icons, our new logo is a callback to CSS’s curly braces and our longstanding B icon. It’s a small upgrade, but a fun one nonetheless, and one that we feel helps set the tone for this new major release. Still the same Bootstrap, just slightly refined. 😅

New Bootstrap docs layout

And the new docs are brighter, better organized with new content sections, and also feature improved navigation.

New offcanvas component

One of our big new component additions is the all-new offcanvas!

Offcanvas example

Built on and sharing fundamental pieces of our modals, our new offcanvas component comes with a configurable backdrop, body scroll, and placement. Offcanvas components can be placed on the top, right, bottom, or left of the viewport. Configure these options with data attributes or via the JavaScript APIs.

New accordion

We’ve replaced our .card accordion component with a brand new .accordion component, solving several bugs in the process. Our new accordion still uses the Collapse JavaScript plugin, but with custom HTML and CSS to support it, it’s better and easier than ever to use.

New Bootstrap accordion

The new accordion includes Bootstrap Icons as chevron icons indicating state and click-ability. We’ve included support for a flush accordion (add .accordion-flush) to remove the outer borders, allowing for easier placement inside parent elements.

Visit the new docs page to learn more.

New and updated forms

We’ve overhauled our Forms documentation and components. We’ve consolidated all our forms styles into a new Forms section (including the input group component) to give them the emphasis they deserve.

New Bootstrap 5 forms docs

Alongside new docs pages, we’ve redesigned and de-duped all our form controls. In v4 we introduced an extensive suite of custom form controls—checks, radios, switches, files, and more—but those were in addition to whatever defaults each browser provided. With v5, we’ve gone fully custom.

Checks and radios

New Bootstrap 5 checks

If you’re familiar with v4’s form markup, this shouldn’t look too far off for you. With a single set of form controls and a focus on redesigning existing elements vs generating new ones via pseudo-elements, we have a much more consistent look and feel.

<div class="form-check">
  <input class="form-check-input" type="checkbox" value="" id="flexCheckDefault">
  <label class="form-check-label" for="flexCheckDefault">
    Default checkbox
  </label>
</div>

<div class="form-check">
  <input class="form-check-input" type="radio" name="flexRadioDefault" id="flexRadioDefault1">
  <label class="form-check-label" for="flexRadioDefault1">
    Default radio
  </label>
</div>

<div class="form-check form-switch">
  <input class="form-check-input" type="checkbox" id="flexSwitchCheckDefault">
  <label class="form-check-label" for="flexSwitchCheckDefault">Default switch checkbox input</label>
</div>

Every checkbox, radio, select, file, range, and more includes a custom appearance to unify the style and behavior of form controls across OS and browser. These new form controls are all built on completely semantic, standard form controls—no more superfluous markup, just form controls and labels.

Floating labels

New floating labels

Floating labels include support for textual inputs, selects, and textareas. We have one limitation with textareas where multiple lines of text can be obscured by the floating label. We’re working on fixes for this, so if you have ideas, please let us know!

New file input

New file input

We’ve dropped our custom .form-file class for additional styles on the .form-control class. This means we no longer require additional JavaScript to make our file input styles functional—the new form file is all CSS!

Simplified layout

Using our new grid updates, form layout has never been easier. We’ve dropped the .form-group.form-row, and .form-inline for the grid system.

New form layout via grid

Be sure to explore the new forms docs and let us know what you think.

RTL is here!

Bootstrap RTL docs

We’ve finally added RTL support to Bootstrap! At a high level, our RTL approach includes a handful of changes:

Our approach is built on RTLCSS, an awesome project that helps reprocess an existing LTR stylesheet for RTL. We’ve classified it as an experimental feature for now, anticipating that we’ll get some of this wrong. We’re looking to the community to help us round out the feature as we wrap up some remaining todos.

Overhauled utilities

Given the love utility-driven frameworks have garnered the last few years, we’ve invested in adding more utilities to Bootstrap along with a new method of managing them across your projects.

New utilities API

We’ve implemented a brand new utility API into Bootstrap 5 as the primary way to extend Bootstrap’s default utility classes. Easily generate and customize utilities with support for custom class names, support for generating state-based classes like :hover, print versions, and more.

$utilities: () !default;
$utilities: map-merge(
  (
    // ...
    "margin": (
      responsive: true,
      property: margin,
      class: m,
      values: map-merge($spacers, (auto: auto))
    ),
    // ...
    "opacity": (
      property: o,
      class: opacity,
      state: hover,
      values: (
        0: 0,
        25: .25,
        50: .5,
        75: .75,
        100: 1,
      )
    )
    // ...
  ), $utilities);

Ever since utilities become a preferred way to build, we’ve been working to find the right balance to implement them in Bootstrap while providing control and customization. In v4, we did this with global $enable-* classes, and we’ve even carried that forward in v5. But with an API-based approach, we’ve created a language and syntax in Sass to create your own utilities on the fly while also being able to modify or remove those we provide.

Head to the new Utilities API docs to learn more.

New utilities

Speaking of utilities, we’ve added a ton of new ones to our arsenal, including:

  • Added positioning utilities: toprightbottom, and left with 050%, and 100% values
  • Added .d-grid option, along with new gap utilities for easy grid layouts
  • Added .fs utilities for font-size
  • Renamed font-weight utilities to .fw
  • Added .rounded-1.rounded-2, and .rounded-3 for new small, medium, and large border-radius utilities
  • Added .overflow-visible and .overflow-scroll utilities

Check out the Migration guide and utilities documentation for more details.

Logical properties for spacing utilities

Part of our approach to adding RTL to Bootstrap was to add it in a way that felt future-friendly to ourselves and the web at large. As such, we’ve embraced the spirit of CSS logical properties and have renamed several classes and variables. It’s a risky change because of the size and impact of the change, but we hope you’ll appreciate it overall!

Most of you have already interacted with logical properties thanks to our flex utilities—they replace direction properties like left and right in favor start and end. Things like align-items-end have been welcomed additions. This makes horizontal directional class names appropriate for LTR and RTL without any additional overhead moving forward.

For example, in a LTR context, instead of .ml-3 for margin-left, use .ms-3. Be sure to read the RTL Migration guide for a full list of renamed classes and variables.

New snippet examples

New examples

We’ve added four brand new snippet-heavy examples and refreshed a few other examples while we were at it. These new snippet examples feature several variations of common components, served up in different ways for you to easily copy and paste.

These new snippets will continue to grow with new additions over time, showing just how fun and easy it is to build with Bootstrap.

New starter example

We’ve also updated our starter template with a refreshed design and more resources.

Grid and layout

Our grid system and layout options saw some changes to streamline and improve things, namely:

  • Column classes can now be used as width utilities (e.g., .col-6 is width: 50%) as padding is no longer applied outside a .row.
  • New gutter utilities can responsively customize horizontal and vertical grid gutters. The gutter width has also been reduced to 1.5rem.
  • Removed position: relative from column classes
  • Dropped the .media component for utilities

We also updated our layout documentation to break apart the exceptionally long pages into more focused topics. We’ve also added a clarified explanation of breakpoints, containers, and more.

Check out the Migration guide and layout documentation for more details.

More component updates

Across the board we’ve made a number of other enhancements and changes to key components:

  • We’ve overhauled the JavaScript and positioning for our dropdowns as part of our adoption of Popper 2. You can see all the options in a new example in our docs and new CSS selectors and data attributes used to position them.
  • Dropdown menus now have a new .dropdown-menu-dark modifier class.
  • Similarly, carousels now have a new .carousel-dark modifier class to invert the controls, text, and indicators.
  • Added icon examples to our Alert component for adding Bootstrap Icons (or other icon libraries) using utilities
  • Our close button has been redesigned with an SVG background-image and improved cross-browser styling.
  • We’ve dropped the .btn-block class for utilities.
  • We’ve updated navbars with a new .navbar-nav-scroll for vertical max-height and scrolling of when a collapsed navbar is opened
  • List groups have a new .list-group-numbered modifier class that uses pseudo-elements to create numbered list group items.

Improved customizing

We’ve hunkered down and improved our documentation in several places, giving more explanation, removing ambiguity, and providing much more support for extending Bootstrap. It all starts with a whole new Customize section.

Bootstrap 5 customize docs

v5’s Customize docs expand on v4’s Theming page with more content and code snippets for building on top of Bootstrap’s source Sass files. We’ve fleshed out more content here and even provided a starter npm project for you to get started with faster and easier. It’s also available as a template repo on GitHub, so you can freely fork and go.

Bootstrap 5 color palette

We’ve expanded our color palette in v5, too. With an extensive color system built-in, you can more easily customize the look and feel of your app without ever leaving the codebase. We’ve also done some work to improve color contrast, and even provided color contrast metrics in our Color docs. Hopefully, this will continue to help make Bootstrap-powered sites more accessible to folks all over.

New Sass docs

We’ve also added new sections to most of our pages to document the source Sass code that powers each component. Variables, mixins, loops, and maps are all rendered and kept up to date in each page, making it easier to reference and customize values as you build.

Dart Sass

We’ve switched to Dart Sass with LibSass being deprecated. We’ve been testing our builds with Dart Sass for a while and decided to make the switch with LibSass being deprecated just a couple of weeks ago. We’re holding on to the Sass modules for now. We’re still not using the new module system for compatibility concerns and a greater gap for folks upgrading from v4.

Browser support

We’ve dropped a ton of older browsers in this update, making it one of our biggest leaps in a while:

  • Dropped Microsoft Edge Legacy
  • Dropped Internet Explorer 10 and 11
  • Dropped Firefox < 60
  • Dropped Safari < 10
  • Dropped iOS Safari < 10
  • Dropped Chrome < 60
  • Dropped Android < 6

You can find the full browser and device support in our .browserslistrc.

JavaScript

The biggest change to our JavaScript has been the removal of jQuery, but we’ve also made a number of enhancements beyond that as well.

  • No more jQuery!
  • All plugins can now accept a CSS selector as the first argument.
  • Updated to Popper 2!
  • Data attributes for all JavaScript plugins are now namespaced with bs. For example, we use data-bs-toggle instead of data-toggle.
  • We overhauled dropdown, popover, and tooltip placement with the arrival of Popper v2.
  • Toast positioning was also overhauled and now leverages our new position utilities.
  • Added ability to use custom classes for tooltips and popovers.
  • Made various optimizations to better share code across components.
  • Changed dropdowns to emit events on .dropdown-toggle instead of .dropdown.
  • Removed underscore from public static methods like _getInstance() to getInstance().
  • Renamed whiteList to allowList in popovers and tooltips

Migration guide

We’ve updated our migration guide page to consolidate all our changes across the six pre-releases into a single set of changes. We’ve condensed much of the content this way and added Breaking change labels throughout to help draw you attention to potential gotchas while upgrading.

We still think there’s more to do here—including tutorial-like guidance on the code changes, diffs and code snippets for our dependencies, etc. If you have suggestions or want to contribute, please open an issue or pull request.


Head to GitHub for a complete list of issues and pull requests in v5.0.0. You can also review the v5.0.0 project board, too.

Get the release

Head to https://getbootstrap.com to explore the new release. We’ve also published this updated as our new latest release on npm, so if you’re feeling bold or are curious about what’s new, you can pull the latest in that way.

npm i bootstrap

Review the GitHub v5.0.0 release changelog for a complete list of changes since our last pre-release.

What’s next

Looking ahead, we’re eyeing our first stable release for Bootstrap 5! But we also have some other releases on the horizon:

Feel free to open issues or pull requests if you have any additional ideas for upcoming releases!

v5.1.0 preview

While we were polishing up this release, we also had our eyes towards the future to ship a few minor releases. Here’s a quick look at what’s coming in our next minor release, v5.1.0:

And more features and updates are planned for a few more releases after that! Check out our projects on GitHub for a closer look.

Support the team

Visit our Open Collective page or our team members’ GitHub profiles to help support the maintainers contributing to Bootstrap.

The Original Article can be found on blog.getbootstrap.com

#bootstrap #html #css #javascript #programming

What is GEEK

Buddha Community

Bootstrap 5 has Officially Released

Volt - Free Bootstrap 5 Admin Dashboard

Volt Bootstrap 5 Dashboard Preview

Volt is a free and open source Bootstrap 5 Admin Dashboard featuring over 100 components, 11 example pages and 3 customized plugins. Volt does not require jQuery as a dependency meaning that every library and script’s are jQuery free.

Bootstrap 5 Components

Because it is created using the latest version of Bootstrap 5, every components and element is based on the latest Bootstrap 5 Sass variables and HTML markup. Check out the documentation of the components here.

11 Example pages

We created no less than 11 advanced example pages such as the overview page, transactions, user settings, sign in and sign up and many more.

Full documentation

Every component, plugin and getting started is thoroughly documented on our online documentation.

Workflow

This product is built using the following widely used technologies:

  • Most popular CSS Framework Bootstrap
  • Productive workflow tool Gulp
  • Awesome CSS preprocessor Sass

Table of Contents

Demo

Dashboard Transactions Settings Forms
Dashboard Transactions Settings Forms
Sign in Sign up Forgot password Reset password
Sign in Sign up Forgot Password Reset password
Lock Profile 404 Not Found 500 Server Error Documentation
Lock Profile 404 Not Found 500 Server Error Documentation

Quick start

  1. Download from Themesberg or clone this repository
  2. Download the project’s zip
  3. Make sure you have Node locally installed.
  4. Download Gulp Command Line Interface to be able to use gulp in your Terminal.
npm install gulp-cli -g
  1. After installing Gulp, run npm install in the main volt/ folder to download all the project dependencies. You’ll find them in the node_modules/ folder.
npm install
  1. Run gulp in the volt/ folder to serve the project files using BrowserSync. Running gulp will compile the theme and open /index.html in your main browser.
gulp

While the gulp command is running, files in the assets/scss/, assets/js/ and components/ folders will be monitored for changes. Files from the assets/scss/ folder will generate injected CSS.

Hit CTRL+C to terminate the gulp command. This will stop the local server from running.

Theme without Sass, Gulp or Npm

If you’d like to get a version of our theme without Sass, Gulp or Npm, we’ve got you covered. Run the following command:

gulp build:dev

This will generate a folder html&css which will have unminified CSS, Html and Javascript.

Minified version

If you’d like to compile the code and get a minified version of the HTML and CSS just run the following Gulp command:

gulp build:dist

This will generate a folder dist which will have minified CSS, Html and Javascript.

Documentation

The documentation for Volt is hosted on our website.

File Structure

Within the download you’ll find the following directories and files:

Volt Bootstrap 5 Admin Dashboard
.
├── README.md
├── gulpfile.js
├── package-lock.json
├── package.json
└── src
    ├── assets
    │   ├── img
    │   └── js
    ├── index.html
    ├── pages
    │   ├── components
    │   ├── dashboard
    │   ├── examples
    │   ├── settings.html
    │   ├── tables
    │   └── transactions.html
    ├── partials
    │   ├── _analytics.html
    │   ├── _footer.html
    │   ├── _head.html
    │   ├── _navigation.html
    │   ├── _pages-preview.html
    │   ├── _preloader.html
    │   ├── _scripts.html
    │   └── dashboard
    └── scss
        ├── volt
        └── volt.scss

Browser Support

At present, we officially aim to support the last two versions of the following browsers:

Resources

Reporting Issues

We use GitHub Issues as the official bug tracker for Volt Bootstrap 5 Admin Dashboard. Here are some advices for our users that want to report an issue:

  1. Make sure that you are using the latest version of Volt Bootstrap 5 Admin Dashboard. Check the CHANGELOG from your dashboard on our website.
  2. Providing us reproducible steps for the issue will shorten the time it takes for it to be fixed.
  3. Some issues may be browser specific, so specifying in what browser you encountered the issue might help.

Technical Support or Questions

If you have questions or need help integrating the product please contact us instead of opening an issue.

Licensing

Useful Links

Social Media

Twitter: https://twitter.com/themesberg

Facebook: https://www.facebook.com/themesberg/

Dribbble: https://dribbble.com/themesberg

Instagram: https://www.instagram.com/themesberg/

#bootstrap #bootstrap5 #bootstrap-5 #bootstrap-5-dashboard #bootstrap-5-admin-dashboard #themesberg

Bootstrap 5 tutorial: how to build a simple admin dashboard interface

Almost 2 months ago Bootstrap 5 alpha has been launched and there are two big news: jQuery has been dropped as a dependency and there is no more direct support for IE 10/11. We’ve been playing around with the new version of the framework and it is exciting to see some features such as the Utility API and working with vanilla JS.

Simple Bootstrap 5 Admin Dashboard Preview

In today’s tutorial, I would like to show you guys how to create a really simple admin dashboard interface using Bootstrap 5. Here’s an online demo if you want to check it out before building it. You’ll create the following sections:

  • A navigation bar with user settings;
  • A sidebar with navigation items;
  • A section to show the title, tagline, and breadcrumbs for the current page;
  • The main content area with a couple of widget cards;
  • Last of but not least a footer.

Read more at Themesberg Blog - Tutorial: How to Build a Simple Admin Dashboard Interface using Bootstrap 5

#tutorial #bootstrap5 #bootstrap-5 #bootstrap-5-dashboard #bootstrap-5-tutorial

Bootstrap 5 Alpha 3 is here: new accordion component, and floating labels

Just about a day ago, I saw on my Twitter feed that Bootstrap 5 Alpha 3 has officially arrived bringing some new features, such as a brand new accordion component, floating labels for input form elements, improvements for the block button component, and a few more utility classes and icons.

Bootstrap 5 Alpha 3

As a refresher, let me remind you that the first version of Bootstrap 5 was launched on the 26th of June, 2020 bringing drastic changes, such as removing jQuery as a dependency and dropping support for Internet Explorer 10 and 11.

Without further ado, let’s see what changes the new Alpha 3 version brings to Bootstrap 5.

Read more about Bootstrap 5 Alpha 3 Changes on Themesberg.

#bootstrap #bootstrap5 #bootstrap-5 #bootstrap-5-alpha- #themesberg

A Django Plugin for Creating AJAX Driven Forms in Bootstrap Modal

Django Bootstrap Modal Forms

A Django plugin for creating AJAX driven forms in Bootstrap modal.

Test and experiment on your machine

This repository includes Dockerfile and docker-compose.yml files so you can easily setup and start to experiment with django-bootstrap-modal-forms running inside of a container on your local machine. Any changes you make in bootstrap_modal_forms, examples and test folders are reflected in the container (see docker-compose.yml) and the data stored in sqlite3 database are persistent even if you remove stopped container. Follow the steps below to run the app:

$ clone repository
$ cd django-bootstrap-modal-forms
$ docker compose up (use -d flag to run app in detached mode in the background)
$ visit 0.0.0.0:8000

Installation

Install django-bootstrap-modal-forms:

$ pip install django-bootstrap-modal-forms

Add bootstrap_modal_forms to your INSTALLED_APPS in settings.py:

INSTALLED_APPS = [
    ...
    'bootstrap_modal_forms',
    ...
]

Include Bootstrap, jQuery and jquery.bootstrap.modal.forms.js on every page where you would like to set up the AJAX driven Django forms in Bootstrap modal.

IMPORTANT: Adjust Bootstrap and jQuery file paths to match yours, but include jquery.bootstrap.modal.forms.js exactly as in code bellow.

<head>
    <link rel="stylesheet" href="{% static 'assets/css/bootstrap.css' %}">
</head>

<body>
    <script src="{% static 'assets/js/bootstrap.js' %}"></script>
    <script src="{% static 'assets/js/jquery.js' %}"></script>
    <script src="{% static 'js/jquery.bootstrap.modal.forms.js' %}"></script>
    <!-- You can alternatively load the minified version -->
    <script src="{% static 'js/jquery.bootstrap.modal.forms.min.js' %}"></script>
</body>

How it works?

index.html

<script type="text/javascript">
$(document).ready(function() {

    $("#create-book").modalForm({
        formURL: "{% url 'create_book' %}"
    });

});
</script>
  1. Click event on html element instantiated with modalForm opens modal
  2. Form at formURL is appended to the modal
  3. On submit the form is POSTed via AJAX request to formURL
  4. Unsuccessful POST request returns errors, which are shown in modal
  5. Successful POST request submits the form and redirects to success_url and shows success_message, which are both defined in related Django view

Usage

1. Form

Define BookModelForm and inherit built-in form BSModalModelForm.

forms.py

from .models import Book
from bootstrap_modal_forms.forms import BSModalModelForm

class BookModelForm(BSModalModelForm):
    class Meta:
        model = Book
        fields = ['title', 'author', 'price']

2. Form's html

Define form's html and save it as Django template.

  • Bootstrap 4 modal elements are used in this example.
  • Form will POST to formURL defined in #6.
  • Add class="invalid" or custom errorClass (see paragraph Options) to the elements that wrap the fields.
  • class="invalid" acts as a flag for the fields having errors after the form has been POSTed.
book/create_book.html

<form method="post" action="">
  {% csrf_token %}

 <div class="modal-header">
    <h5 class="modal-title">Create new Book</h5>
    <button type="button" class="close" data-dismiss="modal" aria-label="Close">
      <span aria-hidden="true">&times;</span>
    </button>
  </div>

  <div class="modal-body">
    {% for field in form %}
      <div class="form-group{% if field.errors %} invalid{% endif %}">
        <label for="{{ field.id_for_label }}">{{ field.label }}</label>
        {{ field }}
        {% for error in field.errors %}
          <p class="help-block">{{ error }}</p>
        {% endfor %}
      </div>
    {% endfor %}
  </div>

  <div class="modal-footer">
    <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
    <button type="submit" class="btn btn-primary">Create</button>
  </div>

</form>

3. Class-based view

Define a class-based view BookCreateView and inherit from built-in generic view BSModalCreateView. BookCreateView processes the form defined in #1, uses the template defined in #2 and redirects to success_url showing success_message.

views.py

from django.urls import reverse_lazy
from .forms import BookModelForm
from .models import Book
from bootstrap_modal_forms.generic import BSModalCreateView

class BookCreateView(BSModalCreateView):
    template_name = 'examples/create_book.html'
    form_class = BookModelForm
    success_message = 'Success: Book was created.'
    success_url = reverse_lazy('index')

4. URL for the view

Define URL for the view in #3.

from django.urls import path
from books import views

urlpatterns = [
    path('', views.Index.as_view(), name='index'),
    path('create/', views.BookCreateView.as_view(), name='create_book'),
]

5. Bootstrap modal and trigger element

Define the Bootstrap modal window and html element triggering modal opening.

  • Single modal can be used for multiple modalForms in single template (see #6).
  • When using multiple modals on the same page each modal should have unique id and the same value should also be set as modalID option when instantiating modalForm on trigger element.
  • Trigger element (in this example button with id="create-book") is used for instantiation of modalForm in #6.
  • Any element can be trigger element as long as modalForm is bound to it.
  • Click event on trigger element loads form's html from #2 within <div class="modal-content"></div> and sets action attribute of the form to formURL set in #6.
index.html

<div class="modal fade" tabindex="-1" role="dialog" id="modal">
  <div class="modal-dialog" role="document">
    <div class="modal-content"></div>
  </div>
</div>

<!-- Create book button -->
<button id="create-book" class="btn btn-primary" type="button" name="button">Create book</button>

6. modalForm

Add script to the template from #5 and bind the modalForm to the trigger element. Set BookCreateView URL defined in #4 as formURL property of modalForm.

  • If you want to create more modalForms in single template using the single modal window from #5, repeat steps #1 to #4, create new trigger element as in #5 and bind the new modalForm with unique URL to it.
  • Default values for modalID, modalContent, modalForm and errorClass are used in this example, while formURL is customized. If you customize any other option adjust the code of the above examples accordingly.
index.html

<script type="text/javascript">
$(document).ready(function() {

    $("#create-book").modalForm({
        formURL: "{% url 'create_book' %}"
    });

});
</script>

Async create/update with or without modal closing on submit

Set asyncUpdate and asyncSettings settings to create or update objects without page redirection to successUrl and define whether a modal should close or stay opened after form submission. See comments in example below and paragraph modalForm options for explanation of asyncSettings. See examples on how to properly reinstantiate modal forms for all CRUD buttons when using async options.
index.html

<!-- asyncSettings.dataElementId -->
<table id="books-table" class="table">
  <thead>
    ...
  </thead>
  <tbody>
  {% for book in books %}
    <tr>
        ...
        <!-- Update book buttons -->
        <button type="button" class="update-book btn btn-sm btn-primary" data-form-url="{% url 'update_book' book.pk %}">
          <span class="fa fa-pencil"></span>
        </button>
        ...
      </td>
    </tr>
  {% endfor %}
  </tbody>
</table>

<script type="text/javascript">
    $(function () {
        ...

        # asyncSettings.successMessage
        var asyncSuccessMessage = [
          "<div ",
          "style='position:fixed;top:0;z-index:10000;width:100%;border-radius:0;' ",
          "class='alert alert-icon alert-success alert-dismissible fade show mb-0' role='alert'>",
          "Success: Book was updated.",
          "<button type='button' class='close' data-dismiss='alert' aria-label='Close'>",
          "<span aria-hidden='true'>&times;</span>",
          "</button>",
          "</div>",
          "<script>",
          "$('.alert').fadeTo(2000, 500).slideUp(500, function () {$('.alert').slideUp(500).remove();});",
          "<\/script>"
        ].join();

        # asyncSettings.addModalFormFunction
        function updateBookModalForm() {
          $(".update-book").each(function () {
            $(this).modalForm({
              formURL: $(this).data("form-url"),
              asyncUpdate: true,
              asyncSettings: {
                closeOnSubmit: false,
                successMessage: asyncSuccessMessage
                dataUrl: "books/",
                dataElementId: "#books-table",
                dataKey: "table",
                addModalFormFunction: updateBookModalForm
              }
            });
          });
        }
        updateBookModalForm();

        ...
    });
</script>
urls.py

from django.urls import path
from . import views

urlpatterns = [
    ...
    # asyncSettings.dataUrl
    path('books/', views.books, name='books'),
    ...
]
views.py

from django.http import JsonResponse
from django.template.loader import render_to_string
from .models import Book

def books(request):
    data = dict()
    if request.method == 'GET':
        books = Book.objects.all()
        # asyncSettings.dataKey = 'table'
        data['table'] = render_to_string(
            '_books_table.html',
            {'books': books},
            request=request
        )
        return JsonResponse(data)

modalForm options

modalID

Sets the custom id of the modal. Default: "#modal"

modalContent

Sets the custom class of the element to which the form's html is appended. If you change modalContent to the custom class, you should also change modalForm accordingly. To keep Bootstrap's modal style you should than copy Bootstrap's style for modal-content and set it to your new modalContent class. Default: ".modal-content"

modalForm

Sets the custom form selector. Default: ".modal-content form"

formURL

Sets the url of the form's view and html. Default: null

isDeleteForm

Defines if form is used for deletion. Should be set to true for deletion forms. Default: false

errorClass

Sets the custom class for the form fields having errors. Default: ".invalid"

asyncUpdate

Sets asynchronous content update after form submission. Default: false

asyncSettings.closeOnSubmit

Sets whether modal closes or not after form submission. Default: false

asyncSettings.successMessage

Sets successMessage shown after succesful for submission. Should be set to string defining message element. See asyncSuccessMessage example above. Default: null

asyncSettings.dataUrl

Sets url of the view returning new queryset = all of the objects plus newly created or updated one after asynchronous update. Default: null

asyncSettings.dataElementId

Sets the id of the element which rerenders asynchronously updated queryset. Default: null

asyncSettings.dataKey

Sets the key containing asynchronously updated queryset in the data dictionary returned from the view providing updated queryset. Default: null

asyncSettings.addModalFormFunction

Sets the method needed for reinstantiation of event listeners on buttons (single or all CRUD buttons) after asynchronous update. Default: null

modalForm default settings object and it's structure

triggerElement.modalForm({
    modalID: "#modal",
    modalContent: ".modal-content",
    modalForm: ".modal-content form",
    formURL: null,
    isDeleteForm: false,
    errorClass: ".invalid",
    asyncUpdate: false,
    asyncSettings: {
        closeOnSubmit: false,
        successMessage: null,
        dataUrl: null,
        dataElementId: null,
        dataKey: null,
        addModalFormFunction: null
    }
});

Forms

Import forms with from bootstrap_modal_forms.forms import BSModalForm.

BSModalForm

Inherits PopRequestMixin and Django's forms.Form.

BSModalModelForm

Inherits PopRequestMixin, CreateUpdateAjaxMixin and Django's forms.ModelForm.

Mixins

Import mixins with from bootstrap_modal_forms.mixins import PassRequestMixin.

PassRequestMixin

Puts the request into the form's kwargs.

PopRequestMixin

Pops request out of the kwargs and attaches it to the form's instance.

CreateUpdateAjaxMixin

Saves or doesn't save the object based on the request type.

DeleteMessageMixin

Deletes object if request is not ajax request.

LoginAjaxMixin

Authenticates user if request is not ajax request.

Generic views

Import generic views with from bootstrap_modal_forms.generic import BSModalFormView.

BSModalFormView

Inherits PassRequestMixin and Django's generic.FormView.

BSModalCreateView

Inherits PassRequestMixin and Django's SuccessMessageMixin and generic.CreateView.

BSModalUpdateView

Inherits PassRequestMixin and Django's SuccessMessageMixin and generic.UpdateView.

BSModalReadView

Inherits Django's generic.DetailView.

BSModalDeleteView

Inherits DeleteMessageMixin and Django's generic.DeleteView.

Examples

To see django-bootstrap-modal-forms in action clone the repository and run the examples locally:

$ git clone https://github.com/trco/django-bootstrap-modal-forms.git
$ cd django-bootstrap-modal-forms
$ pip install -r requirements.txt
$ python manage.py migrate
$ python manage.py runserver

Tests

Run unit and functional tests inside of project folder:

$ python manage.py test

Example 1: Signup form in Bootstrap modal

For explanation how all the parts of the code work together see paragraph Usage. To test the working solution presented here clone and run Examples.

forms.py

from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
from bootstrap_modal_forms.mixins import PopRequestMixin, CreateUpdateAjaxMixin


class CustomUserCreationForm(PopRequestMixin, CreateUpdateAjaxMixin,
                             UserCreationForm):
    class Meta:
        model = User
        fields = ['username', 'password1', 'password2']
signup.html

{% load widget_tweaks %}

<form method="post" action="">
  {% csrf_token %}

  <div class="modal-header">
    <h3 class="modal-title">Sign up</h3>
    <button type="button" class="close" data-dismiss="modal" aria-label="Close">
      <span aria-hidden="true">&times;</span>
    </button>
  </div>

  <div class="modal-body">

    <div class="{% if form.non_field_errors %}invalid{% endif %} mb-2">
      {% for error in form.non_field_errors %}
        {{ error }}
      {% endfor %}
    </div>

    {% for field in form %}
      <div class="form-group">
        <label for="{{ field.id_for_label }}">{{ field.label }}</label>
        {% render_field field class="form-control" placeholder=field.label %}
        <div class="{% if field.errors %} invalid{% endif %}">
          {% for error in field.errors %}
            <p class="help-block">{{ error }}</p>
          {% endfor %}
        </div>
      </div>
    {% endfor %}
  </div>

  <div class="modal-footer">
    <button type="submit" class="btn btn-primary">Sign up</button>
  </div>

</form>
views.py

from django.urls import reverse_lazy
from bootstrap_modal_forms.generic import BSModalCreateView
from .forms import CustomUserCreationForm

class SignUpView(BSModalCreateView):
    form_class = CustomUserCreationForm
    template_name = 'examples/signup.html'
    success_message = 'Success: Sign up succeeded. You can now Log in.'
    success_url = reverse_lazy('index')
urls.py

from django.urls import path
from . import views

app_name = 'accounts'
urlpatterns = [
    path('signup/', views.SignUpView.as_view(), name='signup')
]
.html file containing modal, trigger element and script instantiating modalForm

<div class="modal fade" tabindex="-1" role="dialog" id="modal">
  <div class="modal-dialog" role="document">
    <div class="modal-content"></div>
  </div>
</div>

<button id="signup-btn" class="btn btn-primary" type="button" name="button">Sign up</button>

<script type="text/javascript">
  $(function () {
    // Sign up button
    $("#signup-btn").modalForm({
        formURL: "{% url 'signup' %}"
    });
  });
</script>

Example 2: Login form in Bootstrap modal

For explanation how all the parts of the code work together see paragraph Usage. To test the working solution presented here clone and run Examples.

You can set the login redirection by setting the LOGIN_REDIRECT_URL in settings.py.

You can also set the custom login redirection by:

  1. Adding success_url to the extra_context of CustomLoginView
  2. Setting this success_url variable as a value of the hidden input field with name="next" within the Login form html
forms.py

from django.contrib.auth.forms import AuthenticationForm
from django.contrib.auth.models import User

class CustomAuthenticationForm(AuthenticationForm):
    class Meta:
        model = User
        fields = ['username', 'password']
login.html

{% load widget_tweaks %}

<form method="post" action="">
  {% csrf_token %}

  <div class="modal-header">
    <h3 class="modal-title">Log in</h3>
    <button type="button" class="close" data-dismiss="modal" aria-label="Close">
      <span aria-hidden="true">&times;</span>
    </button>
  </div>

  <div class="modal-body">

    <div class="{% if form.non_field_errors %}invalid{% endif %} mb-2">
      {% for error in form.non_field_errors %}
        {{ error }}
      {% endfor %}
    </div>

    {% for field in form %}
      <div class="form-group">
        <label for="{{ field.id_for_label }}">{{ field.label }}</label>
        {% render_field field class="form-control" placeholder=field.label %}
        <div class="{% if field.errors %} invalid{% endif %}">
          {% for error in field.errors %}
            <p class="help-block">{{ error }}</p>
          {% endfor %}
        </div>
      </div>
    {% endfor %}

    <!-- Hidden input field for custom redirection after successful login -->
    <input type="hidden" name="next" value="{{ success_url }}">
  </div>

  <div class="modal-footer">
    <button type="submit" class="btn btn-primary">Log in</button>
  </div>

</form>
views.py

from django.urls import reverse_lazy
from bootstrap_modal_forms.generic import BSModalLoginView
from .forms import CustomAuthenticationForm

class CustomLoginView(BSModalLoginView):
    authentication_form = CustomAuthenticationForm
    template_name = 'examples/login.html'
    success_message = 'Success: You were successfully logged in.'
    extra_context = dict(success_url=reverse_lazy('index'))
urls.py

from django.urls import path
from . import views

app_name = 'accounts'
urlpatterns = [
    path('login/', views.CustomLoginView.as_view(), name='login')
]
.html file containing modal, trigger element and script instantiating modalForm

<div class="modal fade" tabindex="-1" role="dialog" id="modal">
  <div class="modal-dialog" role="document">
    <div class="modal-content"></div>
  </div>
</div>

<button id="login-btn" class="btn btn-primary" type="button" name="button">Sign up</button>

<script type="text/javascript">
  $(function () {
    // Log in button
    $("#login-btn").modalForm({
        formURL: "{% url 'login' %}"
    });
  });
</script>

Example 3: Django's forms.ModelForm (CRUD forms) in Bootstrap modal

For explanation how all the parts of the code work together see paragraph Usage. To test the working solution presented here clone and run Examples.

forms.py

from .models import Book
from bootstrap_modal_forms.forms import BSModalModelForm


class BookModelForm(BSModalModelForm):
    class Meta:
        model = Book
        exclude = ['timestamp']
create_book.html

{% load widget_tweaks %}

<form method="post" action="">
  {% csrf_token %}

  <div class="modal-header">
    <h3 class="modal-title">Create Book</h3>
    <button type="button" class="close" data-dismiss="modal" aria-label="Close">
      <span aria-hidden="true">&times;</span>
    </button>
  </div>

  <div class="modal-body">

    <div class="{% if form.non_field_errors %}invalid{% endif %} mb-2">
      {% for error in form.non_field_errors %}
        {{ error }}
      {% endfor %}
    </div>

    {% for field in form %}
      <div class="form-group">
        <label for="{{ field.id_for_label }}">{{ field.label }}</label>
        {% render_field field class="form-control" placeholder=field.label %}
        <div class="{% if field.errors %} invalid{% endif %}">
          {% for error in field.errors %}
            <p class="help-block">{{ error }}</p>
          {% endfor %}
        </div>
      </div>
    {% endfor %}
  </div>

  <div class="modal-footer">
    <button type="submit" class="btn btn-primary">Create</button>
  </div>

</form>
update_book.html

{% load widget_tweaks %}

<form method="post" action="">
  {% csrf_token %}

  <div class="modal-header">
    <h3 class="modal-title">Update Book</h3>
    <button type="button" class="close" data-dismiss="modal" aria-label="Close">
      <span aria-hidden="true">&times;</span>
    </button>
  </div>

  <div class="modal-body">
    <div class="{% if form.non_field_errors %}invalid{% endif %} mb-2">
      {% for error in form.non_field_errors %}
        {{ error }}
      {% endfor %}
    </div>

    {% for field in form %}
      <div class="form-group">
        <label for="{{ field.id_for_label }}">{{ field.label }}</label>
        {% render_field field class="form-control" placeholder=field.label %}
        <div class="{% if field.errors %} invalid{% endif %}">
          {% for error in field.errors %}
            <p class="help-block">{{ error }}</p>
          {% endfor %}
        </div>
      </div>
    {% endfor %}
  </div>

  <div class="modal-footer">
    <button type="submit" class="btn btn-primary">Update</button>
  </div>

</form>
read_book.html

{% load widget_tweaks %}

<div class="modal-header">
  <h3 class="modal-title">Book details</h3>
  <button type="button" class="close" data-dismiss="modal" aria-label="Close">
    <span aria-hidden="true">&times;</span>
  </button>
</div>

<div class="modal-body">
  <div class="">
    Title: {{ book.title }}
  </div>
  <div class="">
    Author: {{ book.author }}
  </div>
  <div class="">
    Price: {{ book.price }} €
  </div>
</div>

<div class="modal-footer">
  <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
{% load widget_tweaks %}

<form method="post" action="">
  {% csrf_token %}

  <div class="modal-header">
    <h3 class="modal-title">Delete Book</h3>
    <button type="button" class="close" data-dismiss="modal" aria-label="Close">
      <span aria-hidden="true">&times;</span>
    </button>
  </div>

  <div class="modal-body">
    <p>Are you sure you want to delete book with title
      <strong>{{ book.title }}</strong>?</p>
  </div>

  <div class="modal-footer">
    <button type="submit" class="btn btn-danger">Delete</button>
  </div>

</form>
views.py

from django.urls import reverse_lazy
from django.views import generic
from .forms import BookModelForm
from .models import Book
from bootstrap_modal_forms.generic import (
  BSModalCreateView,
  BSModalUpdateView,
  BSModalReadView,
  BSModalDeleteView
)

class Index(generic.ListView):
    model = Book
    context_object_name = 'books'
    template_name = 'index.html'

# Create
class BookCreateView(BSModalCreateView):
    template_name = 'examples/create_book.html'
    form_class = BookModelForm
    success_message = 'Success: Book was created.'
    success_url = reverse_lazy('index')

# Update
class BookUpdateView(BSModalUpdateView):
    model = Book
    template_name = 'examples/update_book.html'
    form_class = BookModelForm
    success_message = 'Success: Book was updated.'
    success_url = reverse_lazy('index')

# Read
class BookReadView(BSModalReadView):
    model = Book
    template_name = 'examples/read_book.html'

# Delete
class BookDeleteView(BSModalDeleteView):
    model = Book
    template_name = 'examples/delete_book.html'
    success_message = 'Success: Book was deleted.'
    success_url = reverse_lazy('index')
urls.py

from django.urls import path
from books import views

urlpatterns = [
    path('', views.Index.as_view(), name='index'),
    path('create/', views.BookCreateView.as_view(), name='create_book'),
    path('update/<int:pk>', views.BookUpdateView.as_view(), name='update_book'),
    path('read/<int:pk>', views.BookReadView.as_view(), name='read_book'),
    path('delete/<int:pk>', views.BookDeleteView.as_view(), name='delete_book')
]
.html file containing modal, trigger elements and script instantiating modalForms

<!-- Modal 1 with id="create-book"-->
<div class="modal fade" id="create-modal" tabindex="-1" role="dialog" aria-hidden="true">
  <div class="modal-dialog">
    <div class="modal-content">
    </div>
  </div>
</div>

<!-- Modal 2 with id="modal" -->
<div class="modal fade" tabindex="-1" role="dialog" id="modal">
  <div class="modal-dialog" role="document">
    <div class="modal-content"></div>
  </div>
</div>

<!-- Create book button -->
<button id="create-book" class="btn btn-primary" type="button" name="button">Create book</button>

{% for book in books %}
    <div class="text-center">
      <!-- Read book buttons -->
      <button type="button" class="read-book bs-modal btn btn-sm btn-primary" data-form-url="{% url 'read_book' book.pk %}">
        <span class="fa fa-eye"></span>
      </button>
      <!-- Update book buttons -->
      <button type="button" class="update-book bs-modal btn btn-sm btn-primary" data-form-url="{% url 'update_book' book.pk %}">
        <span class="fa fa-pencil"></span>
      </button>
      <!-- Delete book buttons -->
      <button type="button" class="delete-book bs-modal btn btn-sm btn-danger" data-form-url="{% url 'delete_book' book.pk %}">
        <span class="fa fa-trash"></span>
      </button>
    </div>
{% endfor %}

<script type="text/javascript">
  $(function () {

    // Read book buttons
    $(".read-book").each(function () {
        $(this).modalForm({formURL: $(this).data("form-url")});
    });

    // Delete book buttons - formURL is retrieved from the data of the element
    $(".delete-book").each(function () {
        $(this).modalForm({formURL: $(this).data("form-url"), isDeleteForm: true});
    });

    // Create book button opens form in modal with id="create-modal"
    $("#create-book").modalForm({
        formURL: "{% url 'create_book' %}",
        modalID: "#create-modal"
    });

  });
</script>
  • See the difference between button triggering Create action and buttons triggering Read, Update and Delete actions.
  • Within the for loop in .html file the data-form-url attribute of each Update, Read and Delete button should be set to relevant URL with pk argument of the object to be updated, read or deleted.
  • These data-form-url URLs should than be set as formURLs for modalForms bound to the buttons.

Example 4: Django's forms.Form in Bootstrap modal

For explanation how all the parts of the code work together see paragraph Usage. To test the working solution presented here clone and run Examples.

forms.py

from bootstrap_modal_forms.forms import BSModalForm

class BookFilterForm(BSModalForm):
    type = forms.ChoiceField(choices=Book.BOOK_TYPES)

    class Meta:
        fields = ['type']
filter_book.html

{% load widget_tweaks %}

<form method="post" action="">
  {% csrf_token %}

  <div class="modal-header">
    <h3 class="modal-title">Filter Books</h3>
    <button type="button" class="close" data-dismiss="modal" aria-label="Close">
      <span aria-hidden="true">&times;</span>
    </button>
  </div>

  <div class="modal-body">
    <div class="{% if form.non_field_errors %}invalid{% endif %} mb-2">
      {% for error in form.non_field_errors %}
        {{ error }}
      {% endfor %}
    </div>

    {% for field in form %}
      <div class="form-group">
        <label for="{{ field.id_for_label }}">{{ field.label }}</label>
        {% render_field field class="form-control" placeholder=field.label %}
        <div class="{% if field.errors %} invalid{% endif %}">
          {% for error in field.errors %}
            <p class="help-block">{{ error }}</p>
          {% endfor %}
        </div>
      </div>
    {% endfor %}
  </div>

  <div class="modal-footer">
    <button type="submit" class="btn btn-primary">Filter</button>
  </div>

</form>
views.py

class BookFilterView(BSModalFormView):
    template_name = 'examples/filter_book.html'
    form_class = BookFilterForm

    def form_valid(self, form):
        self.filter = '?type=' + form.cleaned_data['type']
        response = super().form_valid(form)
        return response

    def get_success_url(self):
        return reverse_lazy('index') + self.filter
urls.py

from django.urls import path
from . import views

app_name = 'accounts'
urlpatterns = [
    path('filter/', views.BookFilterView.as_view(), name='filter_book'),
]
index.html

  ...
  <button id="filter-book" class="filter-book btn btn-primary" type="button" name="button" data-form-url="{% url 'filter_book' %}">
    <span class="fa fa-filter mr-2"></span>Filter books
  </button>
  ...

  <script type="text/javascript">
    $(function () {
      ...
      $("#filter-book").each(function () {
          $(this).modalForm({formURL: $(this).data('form-url')});
      });
      ...
    });
  </script>

Contribute

This is an Open Source project and any contribution is appreciated.

Live Demo

Demo


Download Details:

Author: trco
Source Code: https://github.com/trco/django-bootstrap-modal-forms

License: MIT license

#django #bootstrap #ajax 

Bootstrap 5: Novedades

Ya tenemos nueva versión de #Bootstrap ¿Novedades? ¿Qué va a pasar en la próxima versión de Odoo?

#bootstrap 5: #bootstrap #what is bootstrap