@ckeditor/ckeditor5-ui
Version:
The UI framework and standard UI library of CKEditor 5.
139 lines (138 loc) • 4.56 kB
JavaScript
/**
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
*/
/**
* @module ui/labeledinput/labeledinputview
*/
import View from '../view.js';
import LabelView from '../label/labelview.js';
import { uid } from '@ckeditor/ckeditor5-utils';
import '../../theme/components/labeledinput/labeledinput.css';
/**
* The labeled input view class.
*/
export default class LabeledInputView extends View {
/**
* The label view.
*/
labelView;
/**
* The input view.
*/
inputView;
/**
* The status view for the {@link #inputView}. It displays {@link #errorText} and
* {@link #infoText}.
*/
statusView;
/**
* Creates an instance of the labeled input view class.
*
* @param locale The locale instance.
* @param InputView Constructor of the input view.
*/
constructor(locale, InputView) {
super(locale);
const inputUid = `ck-input-${uid()}`;
const statusUid = `ck-status-${uid()}`;
this.set('label', undefined);
this.set('value', undefined);
this.set('isReadOnly', false);
this.set('errorText', null);
this.set('infoText', null);
this.labelView = this._createLabelView(inputUid);
this.inputView = this._createInputView(InputView, inputUid, statusUid);
this.statusView = this._createStatusView(statusUid);
this.bind('_statusText').to(this, 'errorText', this, 'infoText', (errorText, infoText) => errorText || infoText);
const bind = this.bindTemplate;
this.setTemplate({
tag: 'div',
attributes: {
class: [
'ck',
'ck-labeled-input',
bind.if('isReadOnly', 'ck-disabled')
]
},
children: [
this.labelView,
this.inputView,
this.statusView
]
});
}
/**
* Creates label view class instance and bind with view.
*
* @param id Unique id to set as labelView#for attribute.
*/
_createLabelView(id) {
const labelView = new LabelView(this.locale);
labelView.for = id;
labelView.bind('text').to(this, 'label');
return labelView;
}
/**
* Creates input view class instance and bind with view.
*
* @param InputView Input view constructor.
* @param inputUid Unique id to set as inputView#id attribute.
* @param statusUid Unique id of the status for the input's `aria-describedby` attribute.
*/
_createInputView(InputView, inputUid, statusUid) {
const inputView = new InputView(this.locale, statusUid);
inputView.id = inputUid;
inputView.ariaDescribedById = statusUid;
inputView.bind('value').to(this);
inputView.bind('isReadOnly').to(this);
inputView.bind('hasError').to(this, 'errorText', value => !!value);
inputView.on('input', () => {
// UX: Make the error text disappear and disable the error indicator as the user
// starts fixing the errors.
this.errorText = null;
});
return inputView;
}
/**
* Creates the status view instance. It displays {@link #errorText} and {@link #infoText}
* next to the {@link #inputView}. See {@link #_statusText}.
*
* @param statusUid Unique id of the status, shared with the input's `aria-describedby` attribute.
*/
_createStatusView(statusUid) {
const statusView = new View(this.locale);
const bind = this.bindTemplate;
statusView.setTemplate({
tag: 'div',
attributes: {
class: [
'ck',
'ck-labeled-input__status',
bind.if('errorText', 'ck-labeled-input__status_error'),
bind.if('_statusText', 'ck-hidden', value => !value)
],
id: statusUid,
role: bind.if('errorText', 'alert')
},
children: [
{
text: bind.to('_statusText')
}
]
});
return statusView;
}
/**
* Moves the focus to the input and selects the value.
*/
select() {
this.inputView.select();
}
/**
* Focuses the input.
*/
focus() {
this.inputView.focus();
}
}