# Upgrade guide for Grid v4.1.0

## Store move method accepts an array

In version 4.1.0, `store.move()` accepts an array in order to move multiple records in one atomic operation. Due to
this, the resulting `move` event now has a `records` property which is the array of records moved. The `record` event
property is deprecated and will be removed in version 5.0.0.

## ColumnPicker Feature now has ability to add new columns based on defined fields in the Model

By configuring the `ColumnPicker` feature with `createColumnsFromModel : true`, fields defined in the grid's store's
`modelClass` appear in the column menu, and can be added as new columns.

```javascript
features : {
    columnPicker : {
        createColumnsFromModel : true
    }
}
```

By default the column header is the uppercased version of the field name. To define a field with a custom column header
text:

```javascript
fields [{
    name : 'priority',
    text : 'Event Level'
}]
```

To exempt a field from being added to the column menu by this feature, configure it with `internal : true`:

```javascript
fields [{
    name     : 'image',
    internal : true
}]
```

## Dropped support for RequireJS

In version 4.1.0 we have removed the RequireJS demo from the project, since it is an outdated technology. We instead
recommend using modern ES6 module imports which is supported in all modern browsers
(Chrome, FireFox, Safari, Edge (chromium)).

You could easily upgrade old application code to use new technology.

**Old code:**

`index.html`

```html
<script data-main="scripts/app" src="scripts/require.js"></script>
```

`scripts/app.js`

```javascript
requirejs.config({
    paths : {
        grid : '../../../build/grid.umd'
    }
});

requirejs(['grid'], function(bryntum) {
    new bryntum.Grid({
        // config here
    });
});
```

**New code:**

`index.html`

```html
<script type="module" src="scripts/app.js"></script>
```

`scripts/app.js`

```javascript
import { Grid } from '../../../build/grid.module.js';

new Grid({
    // config here
});
```

## Prevent listeners from an on-function

Returning `false` from an on-function now prevents any attached listeners from being called. For example:

```javascript
const button = new Button({
    onClick() {
        return false;
    },

    listeners : {
        click() {
            // Won't run when button is clicked, prevented by returning false in onClick() above 
        }
    }
});
```

Prior to this change, the return value of on-functions was not handled at all. We judge the risk of this change as low,
but if you are using both on-functions and listeners on the same instance and are returning a value from the on-function
you might need to adjust your code.

**Old code:**

```javascript
const button = new Button({
    onClick() {
        // Do something
        return false;
    },

    listeners : {
        click() {
            console.log('Click');
        }
    }
});
```

**New code:**

```javascript
const button = new Button({
    onClick() {
        // Do something 
    },

    listeners : {
        click() {
            console.log('Click');
        }
    }
});
```

## Panel Changes

The `Panel` class gained a new wrapper element between the panel's outer `element` and its content element.

Previously, the markup for a `Panel` looked like this:

```html
<div class="b-widget b-container b-panel">
        <header class="b-panel-header b-dock-top"> ... </header>
        <div class="b-panel-content b-content-element">
            <!--...-->
        </div>
</div>
```

The new markup for a `Panel` looks like this:

```html
<div class="b-widget b-container b-panel">
        <header class="b-panel-header b-dock-top"> ... </header>
        <div class="b-panel-body-wrap">    <!-- NEW ELEMENT -->
            <div class="b-panel-content b-content-element">
                <!--...-->
            </div>
        </div>
</div>
```

Any CSS selectors that target immediate children (`>`) of panels will need to be refactored.

For example, selectors like this:

```css
.my-custom-panel > .b-panel-content {
    /*...*/
}
```

Will need to account for the body wrap element:

```css
.my-custom-panel > * > .b-panel-content {
    /*...*/
}
```

Be aware that there will be additional wrapper elements created if toolbars are set `dock` to `left` or `right`. In such
cases, it will be simpler to put the classes on the panel's body element directly using the `bodyCls` config.

## TabPanel Changes

The markup for `TabPanel` in previous releases looks like the following:

```html
<div class="b-widget b-container b-tabpanel b-contains-focus">
        <div class="b-tabpanel-tabs">
            <div class="b-tabpanel-tab b-active"><span class="b-tabpanel-tab-title"> ... </span></div>
            <div class="b-tabpanel-tab"><span class="b-tabpanel-tab-title"> ... </span></div>
        </div>
    </div>
```

There are new elements from the `Panel` base class and from the `Toolbar` base class for the new `TabBar` widget. In
addition, the tabs are now a `Tab` widget which extends `Button`. This changed the tabs from a `<div>/<span>` structure
into a `<button>/<label>` structure.

The markup is now more like the following:

```html
<div class="b-widget b-container b-panel b-tabpanel">

        <!-- New bodyWrap element inherited from Panel: -->
        <div class="b-panel-body-wrap">

            <!-- TabBar is a widget that extends Toolbar: -->
            <div class="b-widget b-container b-toolbar b-tabbar">

                <!-- New scroller overflow tool inherited from Toolbar: -->
                <button class="b-overflow-button b-widget b-tool" />

                <!-- New overflow element containing tabs: -->
                <div class="b-tabpanel-tabs b-toolbar-content b-content-element">

                    <!-- Tabs are now buttons w/their text in a label element: -->
                    <button class="b-widget b-button b-tab b-active"><label>General</label></button>
                    <button class="b-widget b-button b-tab"><label>Predecessors</label></button>
                    <button class="b-widget b-button b-tab"><label>Successors</label></button>
                </div>

                <!-- New scroller overflow tool: -->
                <button class="b-overflow-button b-widget b-tool" />
            </div>
        </div>
    </div>
```

## CSS encoding

Bryntum now uses [Dart SASS](https://sass-lang.com/dart-sass) to compile CSS from SCSS for the themes. It outputs CSS
encoded with UTF-8. The encoding is specified at the top of the CSS file as a `@charset` tag:

```css
@charset "UTF-8";
```

It is important that this tag is preserved in the CSS used on page, to guarantee that font icons render as intended.

Minified CSS instead uses a byte order mark to specify encoding, which although invisible to the eye should be preserved
in the file used on page.

If you use a custom build process that includes our CSS and icons are not rendered correctly in all browsers, the issue
is most likely caused by missing encoding info. Try adding it back or serving the CSS with correct encoding specified in
the HTTP header.

## DatePicker

The DatePicker header DOM structure was refactored and `editOnHover` was deprecated as it no longer has any effect on
the widget. You can safely remove it from your configuration if using it.

## Grid events

The `cellSelector` param of the Grid cellClick / cellDblClick / cellContextMenu / cellMouseOver / cellMouseOut events
was deprecated and will be removed in 5.0

## Grid column header content HTML encoding

Grid column header contents are now HTML encoded by default to protect against XSS attacks. You can easily opt out of
this behavior by setting `htmlEncodeHeaderText` to false on your column.

```javascript
columns : [
    { type : 'name', text : 'Name' },
    { text : 'Responsible<br/>Manager', field : 'manager', width : 100, htmlEncodeHeaderText : false }
]
```

## Framework examples

Frameworks examples were moved to **examples/frameworks** folder:

| Framework | Examples folder             |
|-----------|-----------------------------|
| Angular   | examples/frameworks/angular |
| Ionic     | examples/frameworks/ionic   |
| React     | examples/frameworks/react   |
| Vue v2    | examples/frameworks/vue     |
| Vue v3    | examples/frameworks/vue-3   |


<p class="last-modified">Last modified on 2023-10-26 8:19:11</p>