# Migration guide 15.0.0 -> 16.0.0

## Breaking Changes

### JSF / JavaEE / javax.* support

We completely removed the support of JSF and Java EE and all related javax.* packages.
This means our now baseline is Jakarta Faces 4.0 and newer.

### Client-side widgets

The client-side JavaScript code and build process had some refactorings. Most of this is internal and
will not affect end-users.

All widgets are now proper JavaScript classes. Two points to take note of:

* If you have hacks that modify existing PrimeFaces widgets, you may have to adjust these.
  Overriding prototype method such as `PrimeFaces.widget.SomeWidget.someMethod = function() {... }`
  should still work for the most part. If you need to call the super method from an overridden
  method, you can do so by accessing the prototype method directly, e.g.
  `Object.getPrototypeOf(PrimeFaces.widget.SelectOneMenu).prototype.someSuperMethod.call(this, ...)`.
* If you created custom PrimeFaces widgets that still use the old class emulation syntax,
  you will have to update them. For example, if your widget looks like this:

```js
PrimeFaces.widget.MyWidget = PrimeFaces.widget.DeferredWidget.extend({
    init: function(cfg) {
        this._super(cfg);
        // custom initialization
    },

    refresh: function(cfg) {
        this._super(cfg);
    },
});
```

Then you need to change it to this:

```js
class MyWidget extends PrimeFaces.widget.DeferredWidget {
    init(cfg) {
        super.init(cfg);
        // custom initialization
    }

    refresh(cfg) {
        super.refresh(cfg);
    }
}

PrimeFaces.widget.MyWidget = MyWidget;
```

### Type declarations

PrimeFaces' client-side code now uses TypeScript properly. As part of that change,
there were a few minor changes to the types. The following affects you only if
you were writing custom TypeScript code against PrimeFaces' client-side API
(NPM package `primefaces`):

* As the code is now type checked, a few functions and methods had to have their
  call signature slightly adjusted to reflect reality. You might get some new
  type check errors after the update.
* Values and types were split. Values are now in `PrimeFaces`, types are in
  `PrimeType`. 
  * For example, replace the type `PrimeFaces.widget.PhotoCam.CameraErrorCallback`
    with `PrimeType.widget.PhotoCam.CameraErrorCallback`
  * `PrimeFaces.widget.CommandButton` is only a value, not a type. You can
    use the now type alias `PrimeType.Widget<"CommandButton">` instead.

For reference, to create a custom widget with TypeScript:

```ts
interface MyWidgetCfg extends PrimeType.widget.DeferredWidgetCfg {
    foobar: string;
}

class MyWidget extends PrimeFaces.widget.DeferredWidget<MyWidgetCfg> {
    override init(cfg: PrimeType.widget.PartialWidgetCfg<MyWidgetCfg>): void {
        super.init(cfg);
        // custom initialization
    }

    // optional if you don't need custom logic
    override refresh(cfg: cfg: PrimeType.widget.PartialWidgetCfg<MyWidgetCfg>): void {
        super.refresh(cfg);
    }
}

PrimeFaces.widget.MyWidget = MyWidget;
```

### HTML5 compliance

We removed primefaces.HTML5_COMPLIANCE and Html5FacesContextFactory as its not required anymore with Faces 4.0. The HTML5 doctype is automatically detected from the xhtml.

### PrimeClientWindowLifecycleFactory has been removed

Please use this instead:

```xml
<faces-config>
    <factory>
        <client-window-factory>org.primefaces.clientwindow.PrimeClientWindowFactory</client-window-factory>
    </factory>
</faces-config>
```

### PrimeFlex 4.0.0

PrimeFaces now uses the latest PrimeFlex 4.0.0 library which has some breaking changes if you were using them.

 * Color CSS variables that were `--red-500` are now `--p-red-500` not to clash with other CSS libraries

### Behaviors

The `MixedClientBehaviorHolder` interface method has been renamed to fix a typo and improve type safety:

* The method `getUnobstrusiveEventNames()` has been renamed to `getUnobtrusiveClientBehaviorEventKeys()`
* The return type changed from `Collection<String>` to `Collection<PrimeClientBehaviorEventKeys>`
* Component constants that were misspelled as `UNOBSTRUSIVE_EVENT_KEYS` have been corrected to `UNOBTRUSIVE_EVENT_KEYS`

If you have custom components implementing `MixedClientBehaviorHolder`, update your implementation:

**Before:**
```java
@Override
public Collection<String> getUnobstrusiveEventNames() {
    return Arrays.asList("itemSelect", "itemUnselect");
}
```

**After:**
```java
protected static final List<PrimeClientBehaviorEventKeys> UNOBTRUSIVE_EVENT_KEYS = 
    LangUtils.unmodifiableList(ClientBehaviorEventKeys.itemSelect, ClientBehaviorEventKeys.itemUnselect);

@Override
public Collection<PrimeClientBehaviorEventKeys> getUnobtrusiveClientBehaviorEventKeys() {
    return UNOBTRUSIVE_EVENT_KEYS;
}
```

### Graphic Image

* `cache` now defaults to `false` instead of `true`.

### Tree/TreeTable

* `TreeNodeList` has been removed, just use a `List<TreeNode>`

### Separator

* `p:separator` has been removed, just replace everywhere with a `p:divider`

### DataTable

* Rename `ui-filter-togglable` to `ui-filter-toggleable`

### PrimeFaces Selenium Components

* SelectCheckboxMenu: Rename `togglPanel()` to `togglePanel()`

### Dialog

Rendered markup has been changed from:

```xml
<div class="ui-dialog ui-widget ui-widget-content ui-shadow ui-hidden-container">
    <div class="ui-dialog-titlebar ui-widget-header ui-helper-clearfix">...</div>
    <div class="ui-dialog-content ui-widget-content">...</div>
    <div class="ui-dialog-footer ui-widget-content">...</div>
</div>
```

To the following, so that any long dialog content is now scrollable by default:

```xml
<div class="ui-dialog ui-widget ui-hidden-container">
    <div class="ui-dialog-box ui-widget-content ui-shadow">
        <div class="ui-dialog-titlebar ui-widget-header ui-helper-clearfix">...</div>
        <div class="ui-dialog-content ui-widget-content">...</div>
        <div class="ui-dialog-footer ui-widget-content">...</div>
    </div>
</div>
```
 
* The `ui-dialog` now represents the scrollable layer and the `ui-dialog-box` now represents the actual dialog box.
* The prime use case is that `modal="true" blockScroll="true"` will now finally present a scrollable modal when content is longer than viewport.
* It is recommended to set either `modal="true" blockScroll="true"` *or* `positionType="absolute"` on any `<p:dialog>` with possibly long content, so that no duplicate scrollbars appear, else just use `fitViewport="true"` instead.
* To raise awareness the renderer will now throw `IllegalArgumentException` when `blockScroll="true"` is used *without* `modal="true"` or *with* `positionType="absolute"`.
* Make sure that any custom CSS selectors referencing `ui-dialog` or its children are still compatible.
* The `fitViewport="true"` will now set the `.ui-dialog-fitviewport` class on the `ui-dialog`, like as that `positionType="absolute"` already sets the `ui-dialog-absolute` class.
* Any opened dialog will now set the `ui-dialog-open` class on the HTML body.
* Positioning/dragging/resizing/reopening of `<p:dialog positionType="absolute">` has been improved; previously this was off relative to the window scroll position.
* The window scroll event will not anymore reset the position of any dragged dialog.

### AccordionPanel
* The attribute `activeIndex` has been renamed to `active`, it now supports keys defined with they `key` attribute in `p:tab` alongside indices to smoother handle dynamically rendered tabs. `activeIndex` is now deprecated and wil be removed in a future version.

### SelectOneButton

The accessibility of `p:selectOneButton` has been reworked to the same native-radio model used by `p:selectOneRadio`.
The default layout markup changed from:

```xml
<div id="form:sob" class="ui-selectonebutton ...">
    <div class="ui-button ..." role="radio" aria-checked="true" tabindex="0">
        <input id="form:sob:0" type="radio" class="ui-helper-hidden-accessible" tabindex="-1" aria-label="..."/>
        <span class="ui-button-text ui-c">Option</span>
    </div>
</div>
```

To the following, where the native radio inputs carry focus, keyboard interaction and screen reader semantics:

```xml
<div id="form:sob" class="ui-selectonebutton ..." role="radiogroup" aria-labelledby="form:label">
    <div class="ui-button ...">
        <input id="form:sob:0" type="radio" class="ui-helper-hidden-accessible" tabindex="0"/>
        <label for="form:sob:0" class="ui-button-text ui-c">Option</label>
    </div>
</div>
```

* The visible option text changed from `span.ui-button-text` to `label.ui-button-text` — update any custom CSS or JavaScript selectors referencing `span.ui-button-text` inside a selectOneButton.
* The option containers no longer carry `role="radio"`, `aria-checked` or `tabindex`; keyboard focus now lands on the hidden native radio inputs. Arrow key navigation between options is now supported (native radio group behavior). Style focus via the `.ui-state-focus` class the widget applies to the option container instead of a `:focus` selector on `.ui-button`.
* `SelectOneButton` now implements `org.primefaces.component.api.InputHolder`. A `p:outputLabel for="..."` targeting a selectOneButton now renders a valid `for` attribute pointing at the first radio input and names the radio group via `aria-labelledby` (previously the `for` attribute pointed at the non-labelable root element).
* The `label` attribute of the component is now rendered as `aria-label` on the radio group when no `p:outputLabel` is attached.
* The custom layout (`layout="custom"` or the `custom` facet) is unaffected.
