Options
All
  • Public
  • Public/Protected
  • All
Menu

Namespace PageTable

Содержание

  1. Просто таблица
  2. Заполняем данными
  3. bindingProperty
  4. Заголовок и сетка
  5. Описание элементов
  6. Выделением ячеек
  7. Элементы ячеек - устанавливаем данные
  8. Меню и выравнивание в ячейках
  9. tabindex и обработчики событий focus, keydown

1. Просто таблица

Замените содержимое simple.ts из примера в статье "Начало работы" следующим содержанием и пресоберите приложение:

/*Инструкции для WebPack, который скопирует эти файлы в ваш каталог*/
import './index.html';
import 'ui-organizer/page.css';
import 'ui-organizer/style.css';
import 'ui-organizer/vars.css';

/*Описание формы simpleForm*/
import type {IForm, ITable} from "ui-organizer";
import { AppManager, UIForm, UITable} from "ui-organizer";

export let form: IForm = <IForm>{
    type: UIForm,
    name: 'simpleForm',
    elements: [
        <ITable>{
            type: UITable,
            columns: [{}, {}, {}],
            value: [
                ["Михаил", "м", "29"],
                ["Дмитрий", "м", "26"],
                ["Анна", "ж", "20"],
            ]
        }
    ]
}

/*Инициализация приложения AppManager*/
var Global: any = window;
Global.AppManager = AppManager;
Global.onpopstate = AppManager.onPopState;

AppManager.init(document.querySelector('#app'))
    .then(async ()=>{
        AppManager.add([form]);
        AppManager.open('simpleForm', {});
    })

Здесь мы создали простую форму с единственным элементом ITable и указали у элемента ITable свойство value. Обратите внимание, что в свойстве columns мы просто обозначили три столбца, не указывая их название и других свойств. Если свойство columns не задавать, то получите пустую таблицу.

2. Заполняем данными

Замените содержимое simple.ts из примера в статье "Начало работы" следующим содержанием и пресоберите приложение:

/*Инструкции для WebPack, который скопирует эти файлы в ваш каталог*/
import './index.html';
import 'ui-organizer/page.css';
import 'ui-organizer/style.css';
import 'ui-organizer/vars.css';

/*Описание формы simpleForm*/
import type {IForm, ITable} from "ui-organizer";
import { AppManager, UIForm, UITable} from "ui-organizer";

export let form: IForm = <IForm>{
    type: UIForm,
    name: 'simpleForm',
    elements: [
        <ITable>{
            type: UITable,
            name: 'myTable',
            columns: [{}, {}],
            //value: undefined,
        }
    ]
}

let data = [
    ["Михаил"],
    ["Дмитрий", "м"],
    ["Анна", "ж", "20"],
]

/*Инициализация приложения AppManager*/
var Global: any = window;
Global.AppManager = AppManager;
Global.onpopstate = AppManager.onPopState;

AppManager.init(document.querySelector('#app'))
    .then(async ()=>{
        AppManager.add([form]);
        AppManager.open('simpleForm', data);
    })

Здесь мы создали простую форму с единственным элементом ITable и передали ей данные data. Как вы можете заметить мы не указали какими элементами будут строки списка и откуда брать данные.
Форма передала таблице данные целиком и таблица увидев массив, просто сформировала из него строки.

Несколько пояснений:

  • Во-первых, столбцы, опять же, мы просто обозначили без указания названий и других свойств.
  • Во-вторых, свойство value убрали, т.е. оно имеет значение undefined. Иначе таблица не будет заполняться данными.
  • В-третьих, мы специально здали два столбца, а данные предали разные: в первой строке одно значение, во второй строке два значения, в третьей строке три значения (посмотрите что будет).

Причем данные строк - это те данные, которые мы передали форме. Вы можете убедится в этом вызвав средство разработчика в браузере (F12) и выполнив в консоли следующий код:

AppManager.activeForm.getElement('myTable').rows.toArray()[2].getData()

В таблице свойство rows это объект ItemsList, поэтому преобразуем его в массив. Мы увидим данные третьей строки. Название таблицы мы указали в описании специально, чтобы вызвать этот код в консоли.

3. bindingProperty

Добавьте bindingProperty в описание таблицы и соответствующее свойство в данные:

/*Инструкции для WebPack, который скопирует эти файлы в ваш каталог*/
import './index.html';
import 'ui-organizer/page.css';
import 'ui-organizer/style.css';
import 'ui-organizer/vars.css';

/*Описание формы simpleForm*/
import type {IForm, ITable} from "ui-organizer";
import { AppManager, UIForm, UITable} from "ui-organizer";

export let form: IForm = <IForm>{
    type: UIForm,
    name: 'simpleForm',
    elements: [
        <ITable>{
            type: UITable,
            name: 'myTable',
            columns: [{}, {}, {}],
            //value: undefined,
            bindingProperty: 'tableData'
        }
    ]
}

let data = {
    tableData: [
        ["Михаил", "м", "29"],
        ["Дмитрий", "м", "26"],
        {
            name:"Анна", 
            sex:"ж", 
            age:"20"
        },
    ],
    anotherData: {}
}

/*Инициализация приложения AppManager*/
var Global: any = window;
Global.AppManager = AppManager;
Global.onpopstate = AppManager.onPopState;

AppManager.parent = document.querySelector('#app');
AppManager.add([form]);
AppManager.open('simpleForm', data, undefined);

Таблица получает данные из свойства tableData.
Обратите внимание, что данные третьей строки - это объект, а не массив. Мы специально так сделали, чтобы продемонстрировать, что в строку таблицы вы можете передавать объекты. Причем данные остаются те, которые вы передали. Вы можете убедится в этом вызвав средство разработчика в браузере (F12) и выполнив в консоли следующий код:

AppManager.activeForm.getElement('myTable').rows.toArray()[0].getData()
AppManager.activeForm.getElement('myTable').rows.toArray()[1].getData()
AppManager.activeForm.getElement('myTable').rows.toArray()[2].getData()

4. Заголовок и сетка

Давайте опишем заголовок и зададим сетку. Для этого в таблице добавим два свойства: grided и showHeader, а в свойстве columns опишем заголовок столбца (header).

/*Инструкции для WebPack, который скопирует эти файлы в ваш каталог*/
import './index.html';
import 'ui-organizer/page.css';
import 'ui-organizer/style.css';
import 'ui-organizer/vars.css';

/*Описание формы simpleForm*/
import type {IForm, ITable} from "ui-organizer";
import { AppManager, JustifyContent, UIForm, UITable} from "ui-organizer";

export let form: IForm = <IForm>{
    type: UIForm,
    name: 'simpleForm',
    elements: [
        <ITable>{
            type: UITable,
            name: 'myTable',
            grided: true,
            showHeader: true,
            columns: [{
                header: "Имя",
                justifyContent: JustifyContent.left
            }, {
                header: "Пол",
                justifyContent: JustifyContent.center
            }, {
                header: "Возраст",
                justifyContent: JustifyContent.right
            }],
            //value: undefined,
            bindingProperty: 'tableData'
        }
    ]
}

let data = {
    tableData: [
        ["Михаил", "м", "29"],
        ["Дмитрий", "м", "26"],
        {
            name:"Анна", 
            sex:"ж", 
            age:"20"
        },
    ],
    anotherData: {}
}

/*Инициализация приложения AppManager*/
var Global: any = window;
Global.AppManager = AppManager;
Global.onpopstate = AppManager.onPopState;

AppManager.init(document.querySelector('#app'))
    .then(async ()=>{
        AppManager.add([form]);
        AppManager.open('simpleForm', data);
    })

В описании колонки мы добавили свойство justifyContent. Оно выравнивает контент только заголовка. Чтобы выровнять контент содержимого строк необходимо задать элемент, который подставляется в ячейку строки (см. следующий раздел).

5. Описание элементов

Для ячейки таблицы можно задать любой элемент формы, например: IDataElement, IStr и др (элемент должен быть наследником IDataElement). Для этого в свойстве columns опишем элемент столбца (itemsElement).

/*Инструкции для WebPack, который скопирует эти файлы в ваш каталог*/
import './index.html';
import 'ui-organizer/page.css';
import 'ui-organizer/style.css';
import 'ui-organizer/vars.css';

/*Описание формы simpleForm*/
import type {IDataElement, IForm, ITable} from "ui-organizer";
import { AppManager, JustifyContent, UIDataElement, UIForm, UITable} from "ui-organizer";

export let form: IForm = <IForm>{
    type: UIForm,
    name: 'simpleForm',
    elements: [
        <ITable>{
            type: UITable,
            name: 'myTable',
            grided: true,
            showHeader: true,
            columns: [{
                header: "Имя",
                justifyContent: JustifyContent.left,
                itemsElement: <IDataElement>{
                    type: UIDataElement,
                    justifyContent: JustifyContent.left,
                    bindingProperty: 'name'
                }
            }, {
                header: "Пол",
                justifyContent: JustifyContent.center,
                itemsElement: <IDataElement>{
                    type: UIDataElement,
                    justifyContent: JustifyContent.center,
                    bindingProperty: 'sex'
                }
            }, {
                header: "Возраст",
                justifyContent: JustifyContent.right,
                itemsElement: <IDataElement>{
                    type: UIDataElement,
                    justifyContent: JustifyContent.right,
                    bindingProperty: 'age'
                }
            }],
            //value: undefined,
            bindingProperty: 'tableData'
        }
    ]
}

let data = {
    tableData: [
        {
            age:"29",
            name:"Михаил", 
            sex:"м" 
        },
        {
            sex: "м", 
            age:"26",
            name:"Дмитрий"
        },
        {
            name: "Анна", 
            age:"20",
            sexy:"ж" 
        },
    ],
    anotherData: {}
}

/*Инициализация приложения AppManager*/
var Global: any = window;
Global.AppManager = AppManager;
Global.onpopstate = AppManager.onPopState;

AppManager.init(document.querySelector('#app'))
    .then(async ()=>{
        AppManager.add([form]);
        AppManager.open('simpleForm', data);
    })

В свойстве itemsElement мы указали элемент IDataElement, у которого задали:

  • способ выравнивания в строке (justifyContent)
  • откуда брать данные (bindingProperty).

В переменной data мы указали объекты, где поменяли местами все ключи. Причем, у Анны специально ошиблись в написании ключа sex. Как видите таблица заполнена правильно и данные заданы такие, какие есть. Проверьте также:

AppManager.activeForm.getElement('myTable').rows.toArray()[2].getData()

6. Выделение ячеек

Добавьте два свойства в описание таблицы: allowSelectCell и multipleSelect.

/*Инструкции для WebPack, который скопирует эти файлы в ваш каталог*/
import './index.html';
import 'ui-organizer/page.css';
import 'ui-organizer/style.css';
import 'ui-organizer/vars.css';

/*Описание формы simpleForm*/
import type {IDataElement, IForm, ITable} from "ui-organizer";
import { AppManager, JustifyContent, MultipleSelect, UIDataElement, UIForm, UITable} from "ui-organizer";

export let form: IForm = <IForm>{
    type: UIForm,
    name: 'simpleForm',
    elements: [
        <ITable>{
            type: UITable,
            name: 'myTable',
            grided: true,
            showHeader: true,
            allowSelectCell: true,
            multipleSelect: MultipleSelect.ctrlKey,
            columns: [{
                header: "Имя",
                justifyContent: JustifyContent.left,
                itemsElement: <IDataElement>{
                    type: UIDataElement,
                    justifyContent: JustifyContent.left,
                    bindingProperty: 'name'
                }
            }, {
                header: "Пол",
                justifyContent: JustifyContent.center,
                itemsElement: <IDataElement>{
                    type: UIDataElement,
                    justifyContent: JustifyContent.center,
                    bindingProperty: 'sex'
                }
            }, {
                header: "Возраст",
                justifyContent: JustifyContent.right,
                itemsElement: <IDataElement>{
                    type: UIDataElement,
                    justifyContent: JustifyContent.right,
                    bindingProperty: 'age'
                }
            }],
            //value: undefined,
            bindingProperty: 'tableData'
        }
    ]
}

let data = {
    tableData: [
        {
            age:"29",
            name:"Михаил", 
            sex:"м" 
        },
        {
            sex: "м", 
            age:"26",
            name:"Дмитрий"
        },
        {
            name: "Анна", 
            age:"20",
            sex:"ж" 
        },
    ],
    anotherData: {}
}

/*Инициализация приложения AppManager*/
var Global: any = window;
Global.AppManager = AppManager;
Global.onpopstate = AppManager.onPopState;

AppManager.init(document.querySelector('#app'))
    .then(async ()=>{
        AppManager.add([form]);
        AppManager.open('simpleForm', data);
    })

В свойстве multipleSelect указывается какой клавишей выделять несколько ячеек MultipleSelect.ctrlKey.

7. Элементы ячеек - устанавливаем данные

В предыдущих двух разделах 5 и 6 мы установили элемент управления IDataElement в каждую ячейку, и указали bindingProperty, что брать данные надо в конкретном свойстве. Если не указывать bindingProperty, то данные будут подставляться в каждый столбец из соответствующего свойства по порядку, как показано в разделе 3 (там мы в последней строке передали объект).

Как быть, если нужно в ячейку передать объект строки целиком, а не отдельное свойство? Вы можете в элементе IDataElement столбца в свойстве bindingProperty указать значение '.'

В следующем примере мы оставили два столбца, и в первый столбец передали объект строки целиком:

/*Инструкции для WebPack, который скопирует эти файлы в ваш каталог*/
import './index.html';
import 'ui-organizer/page.css';
import 'ui-organizer/style.css';
import 'ui-organizer/vars.css';

/*Описание формы simpleForm*/
import type {IDataElement, IForm, ITable} from "ui-organizer";
import { AppManager, JustifyContent, MultipleSelect, UIDataElement, UIForm, UITable} from "ui-organizer";

export let form: IForm = <IForm>{
    type: UIForm,
    name: 'simpleForm',
    elements: [
        <ITable>{
            type: UITable,
            name: 'myTable',
            grided: true,
            showHeader: true,
            allowSelectCell: true,
            multipleSelect: MultipleSelect.ctrlKey,
            columns: [{
                header: "Имя",
                justifyContent: JustifyContent.left,
                itemsElement: <IDataElement>{
                    type: UIDataElement,
                    justifyContent: JustifyContent.left,
                    // bindingProperty: 'name',
                    bindingProperty: '.',
                    async onBeforeSetData(e) {
                        let data = e.data;
                        e.data = `${data.name} (${data.sex})` ;
                    }
                }
            },  {
                header: "Возраст",
                justifyContent: JustifyContent.right,
                itemsElement: <IDataElement>{
                    type: UIDataElement,
                    justifyContent: JustifyContent.right,
                    bindingProperty: 'age'
                }
            }],
            bindingProperty: 'tableData'
        }
    ]
}

let data = {
    tableData: [
        {
            age:"29",
            name:"Михаил", 
            sex:"м" 
        },
        {
            sex: "м", 
            age:"26",
            name:"Дмитрий"
        },
        {
            name: "Анна", 
            age:"20",
            sex:"ж" 
        },
    ],
    anotherData: {}
}

/*Инициализация приложения AppManager*/
var Global: any = window;
Global.AppManager = AppManager;
Global.onpopstate = AppManager.onPopState;

AppManager.init(document.querySelector('#app'))
    .then(async ()=>{
        AppManager.add([form]);
        AppManager.open('simpleForm', data);
    })

8. Меню и выравнивание в ячейках

Для добавления иконок в меню таблицы добавьте на страницу загрузку скриптов fontAwesome:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>ui-organizer simple form</title>
    <link rel="stylesheet" href="page.css">
    <link rel="stylesheet" href="style.css">    
    <!-- Например --><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/css/all.min.css">
    <style>
        /* Просто, поместили форму посередине страницы */
        body { width: 50%; margin: 0px auto 0px auto}
    </style>
</head>
<body>
    <div id="app">
    </div>
    <script type="text/javascript" src="index.js"></script>
</body>
</html>

Но, в связи с блокированием cdn сервисов в России этот вариант вас может не устроить. Вы можете сделать по-другому - скачать бибилиотеку fontawesome:

Смотреть как...
  1. Установите необходимые библиотеки:

    npm install @fortawesome/fontawesome-free copy-webpack-plugin
    
  2. Измените файл webpack.config.js добавив copy-webpack-plugin: ```javascript const path = require('path'); const UIOrganizerWebpackPlugin = require('ui-organizer-webpack-plugin'); /---Добавили copy-webpack-plugin/ const CopyPlugin = require("copy-webpack-plugin"); /---/

module.exports = { mode: 'development', entry: './simple.ts', output: { filename: 'index.js', path: path.resolve(__dirname, ./dist), assetModuleFilename: '[name][ext]' }, module: { rules: [ { test: /.ts?$/, use: 'ts-loader' }, { test: /.css$/, type: 'asset/resource',
}, { test: /.html$/, type: 'asset/resource', },
], }, plugins: [ new UIOrganizerWebpackPlugin(), /---Добавили copy-webpack-plugin*/
new CopyPlugin({ patterns: [ /*Копируем шрифты и таблицы стилей в папку ./dist/ { from: "./node_modules/@fortawesome/fontawesome-free", to: "./fontawesome-free" }, ], }), /
---*/ ], resolve: { extensions: ['.ts', '.js'], } };


3. Добавьте соответствующую строку в html:
```html
<!DOCTYPE html>
<html>
<head>
    ...
    <link rel="stylesheet" href="fontawesome-free/css/all.min.css"><!--скопирован программой webpack в ./dist/fontawesome-free/css из папки node_modules/@fortawesome/fontawesome-free/css/all.min.css-->    
</head>
...

Расширим описание таблицы из раздела 6 и добавим меню в таблицу, а также укажем для элементов столбцов способы выравнивания в ячейке.

В примере ниже мы добавили переменную menu, которую передали в одноименное свойство таблицы. В меню добавили три кнопки add, remove, edit и для каждой кнопки написали обработчик onClick:

  • Для добавления строки получаем таблицу и вызываем метод addRow(). Мы не передаем данные в метод addRow, т.к. в этом случае будет заполнено значение (value), а вместо этого у новой строки устанавливаем данные в методе setData().
  • Для удаления строки получаем таблицу. Получаем выбранные строки, если получили пустой массив, то получаем выбранные ячейки. И уже потом перебираем массив и удаляем строки. Конечно можно сразу получить выбранные ячейки. Мы старались написать более универсальный код, который бы подошел и для таблиц, где можно выбирать только строки, и для таблиц, где можно выбирать только ячейки.
  • Для редактирования вызываем метод edit таблицы. Будет вызван метод edit() элемента выбранной ячейки.

Также, мы для элемента колонки (itemsElement) добавили свойство alignSelf. В отличие от justifyContent это свойство позволяет выравнивать содержимое ячейки еще и по вертикали.

Еще, мы для каждой колонки указали фиксированный размер свойство size. Без него ширина колонки будет изменяться в процессе ввода текста при редактировании таблицы.

/*Инструкции для WebPack, который скопирует эти файлы в ваш каталог*/
import './index.html';
import 'ui-organizer/page.css';
import 'ui-organizer/style.css';
import 'ui-organizer/vars.css';

/*Описание формы simpleForm*/
import type {ICell, IDataElement, IFigAwesome, IForm, IMenu, IMenuItem, IRow, ITable} from "ui-organizer";
import { AppManager, IconDisplay, UIForm, UIMenu, UIMenuItem, UITable, UIMouseEvent, JustifyContent, UIDataElement, AlignSelf} from "ui-organizer";

let menu = <IMenu>{
    type: UIMenu,
    elements: [
        <IMenuItem>{
            type: UIMenuItem,
            caption: 'add',
            iconDisplay: IconDisplay.icon,
            figAwesome: <IFigAwesome>{
                faClass: ['fas', 'fa-plus', 'fa-lg'],
                faStyle: ['color: grey;']
            },
            async onClick(event:UIMouseEvent, form: IForm, menu: IMenu, menuItem: IMenuItem) {
                let table: ITable = form.getElement(this.parent.owner.name) as ITable;
                let row: IRow = await table.addRow();
                row.setData({name:"Имя", sex:"Пол", age:"Возраст"});

            }
        },
        <IMenuItem>{
            type: UIMenuItem,
            caption: 'remove',
            iconDisplay: IconDisplay.icon,
            figAwesome: <IFigAwesome>{
                faClass: ['fas', 'fa-minus', 'fa-lg'],
                faStyle: ['color: grey;']
            },
            async onClick(event:UIMouseEvent, form: IForm, menu: IMenu, menuItem: IMenuItem) {
                let table: ITable = form.getElement(this.parent.owner.name) as ITable;
                let selected: Array<IRow | ICell> = table.getSelectedRows();
                if (selected.length == 0) selected = table.getSelectedCells();
                selected.forEach(item=>{
                    let id: string = (<IRow>item).id == undefined ? (<ICell>item).row.id : (<IRow>item).id;
                    table.removeRow(id);
                })
            }
        },
        <IMenuItem>{
            type: UIMenuItem,
            caption: 'edit',
            iconDisplay: IconDisplay.icon,
            figAwesome: <IFigAwesome>{
                faClass: ['fas', 'fa-edit', 'fa-lg'],
                faStyle: ['color: grey;']
            },
            async onClick(event:UIMouseEvent, form: IForm, menu: IMenu, menuItem: IMenuItem) {
                let table: ITable = form.getElement(this.parent.owner.name) as ITable;
                table.edit();   
            }
        }
    ]
}

export let form: IForm = <IForm>{
    type: UIForm,
    name: 'simpleForm',
    elements: [
        <ITable>{
            type: UITable,
            name: 'myTable',
            grided: true,
            // showHeader: true,
            allowSelectCell: true,
            // multipleSelect: MultipleSelect.ctrlKey,            
            menu: menu,
            columns: [{
                header: "Имя",
                justifyContent: JustifyContent.left,
                itemsElement: <IDataElement>{
                    type: UIDataElement,                    
                    alignSelf: AlignSelf.topLeft,/**Выравнивание не только по горизонтали, но и по вертикали*/
                    // justifyContent: JustifyContent.left,
                    bindingProperty: 'name'
                },
                size:'40%'/**Ширина колонки*/
            }, {
                header: "Пол",
                justifyContent: JustifyContent.center,
                itemsElement: <IDataElement>{
                    type: UIDataElement,
                    alignSelf: AlignSelf.topCenter,/**Выравнивание не только по горизонтали, но и по вертикали*/
                    // justifyContent: JustifyContent.center,
                    bindingProperty: 'sex'
                },
                size:'30%'/**Ширина колонки*/
            }, {
                header: "Возраст",
                justifyContent: JustifyContent.right,
                itemsElement: <IDataElement>{
                    type: UIDataElement,                    
                    alignSelf: AlignSelf.topCenter,/**Выравнивание не только по горизонтали, но и по вертикали*/
                    // justifyContent: JustifyContent.center,
                    bindingProperty: 'age'
                },
                size:'30%'/**Ширина колонки*/
            }],
            //value: undefined,
            bindingProperty: 'tableData', 
            bordered: true
        }
    ]
}

let data = {
    tableData: [
        {
            age:"29",
            name:"Михаил", 
            sex:"м" 
        },
        {
            sex: "м", 
            age:"26",
            name:"Дмитрий"
        },
        {
            name: "Анна", 
            age:"20",
            sex:"ж" 
        },
    ],
    anotherData: {}
}

/*Инициализация приложения AppManager*/
var Global: any = window;
Global.AppManager = AppManager;
Global.onpopstate = AppManager.onPopState;

AppManager.init(document.querySelector('#app'))
    .then(async ()=>{
        AppManager.add([form]);
        AppManager.open('simpleForm', data);
    })

9. tabindex и обработчики событий focus, keydown

Изменим код для осуществления навигации между элементами с помощью клавиатуры и отслеживания вызовов событий на каждое действие.

  • Добавим свойство tabindex в таблицу и кнопки меню.
  • В методе onAfrterLoad каждого элемента добавим вызов функции assignListeners(), в которой устанавливаем обработчки событий focus, blur, keydown, keyup, beforeEdit, afterEdit.
  • В кнопках меню добавим обработчик onKeyDown, где при нажатии клавиши 'Enter' выполняем те же действия, что при 'onclick'.
  • Добавление прослушивателей assignListeners() в элементы ячеек таблицы сделаем в методе onAfterAddRow() таблицы.
/*Инструкции для WebPack, который скопирует эти файлы в ваш каталог*/
import './index.html';
import 'ui-organizer/page.css';
import 'ui-organizer/style.css';
import 'ui-organizer/vars.css';

/*Описание формы simpleForm*/
import type {ICell, IDataElement, IElement, IFigAwesome, IForm, IMenu, IMenuItem, IRow, ITable} from "ui-organizer";
import { AppManager, IconDisplay, UIForm, UIMenu, UIMenuItem, UITable, UIMouseEvent, JustifyContent, UIDataElement, AlignSelf} from "ui-organizer";
import {UIRowEvent, UIEditEvent, UIFocusEvent, UIKeyboardEvent} from "ui-organizer";

let menu = <IMenu>{
    type: UIMenu,
    elements: [
        <IMenuItem>{
            type: UIMenuItem,
            caption: 'add',
            iconDisplay: IconDisplay.icon,
            figAwesome: <IFigAwesome>{
                faClass: ['fas', 'fa-plus', 'fa-lg'],
                faStyle: ['color: grey;']
            },
            tabindex: 0,
            async onKeyDown(event, form, elem, item) {
                if (event.key == 'Enter') {
                    let table: ITable = form.getElement(this.parent.owner.name) as ITable;
                    let row: IRow = await table.addRow();
                    row.setData({name:"Имя", sex:"Пол", age:"Возраст"});
                }                           
            },
            async onClick(event:UIMouseEvent, form: IForm, menu: IMenu, menuItem: IMenuItem) {
                let table: ITable = form.getElement(this.parent.owner.name) as ITable;
                let row: IRow = await table.addRow();
                row.setData({name:"Имя", sex:"Пол", age:"Возраст"});

            },
            async onAfterLoad(event, form, elem) {
                assignListeners('           MenuItem add:', elem);
            }
        },
        <IMenuItem>{
            type: UIMenuItem,
            caption: 'remove',
            iconDisplay: IconDisplay.icon,
            figAwesome: <IFigAwesome>{
                faClass: ['fas', 'fa-minus', 'fa-lg'],
                faStyle: ['color: grey;']
            },
            tabindex: 0,
            async onKeyDown(event, form, elem, item) {
                if (event.key == 'Enter') {
                    let table: ITable = form.getElement(this.parent.owner.name) as ITable;
                    let selected: Array<IRow | ICell> = table.getSelectedRows();
                    if (selected.length == 0) selected = table.getSelectedCells();
                    selected.forEach(item=>{
                        let id: string = (<IRow>item).id == undefined ? (<ICell>item).row.id : (<IRow>item).id;
                        table.removeRow(id);
                    })
                }                           
            },
            async onClick(event:UIMouseEvent, form: IForm, menu: IMenu, menuItem: IMenuItem) {
                let table: ITable = form.getElement(this.parent.owner.name) as ITable;
                let selected: Array<IRow | ICell> = table.getSelectedRows();
                if (selected.length == 0) selected = table.getSelectedCells();
                selected.forEach(item=>{
                    let id: string = (<IRow>item).id == undefined ? (<ICell>item).row.id : (<IRow>item).id;
                    table.removeRow(id);
                })
            },
            async onAfterLoad(event, form, elem) {
                assignListeners('           MenuItem remove:', elem);
            }
        },
        <IMenuItem>{
            type: UIMenuItem,
            caption: 'edit',
            iconDisplay: IconDisplay.icon,
            figAwesome: <IFigAwesome>{
                faClass: ['fas', 'fa-edit', 'fa-lg'],
                faStyle: ['color: grey;']
            },
            tabindex: 0,
            async onKeyDown(event, form, elem, item) {
                if (event.key == 'Enter') {
                    let table: ITable = form.getElement(this.parent.owner.name) as ITable;
                    table.edit();   
                }                           
            },
            async onClick(event:UIMouseEvent, form: IForm, menu: IMenu, menuItem: IMenuItem) {
                let table: ITable = form.getElement(this.parent.owner.name) as ITable;
                table.edit();   
            },
            async onAfterLoad(event, form, elem) {
                assignListeners('           MenuItem edit:', elem);
            }
        }
    ],
    async onAfterLoad(event, form, elem) {
        assignListeners('       Menu:', elem);
    }
}

export let form: IForm = <IForm>{
    type: UIForm,
    name: 'simpleForm',
    elements: [
        <ITable>{
            type: UITable,
            name: 'myTable',
            grided: true,
            // showHeader: true,
            allowSelectCell: true,
            // multipleSelect: MultipleSelect.ctrlKey,            
            menu: menu,
            columns: [{
                header: "Имя",
                justifyContent: JustifyContent.left,
                itemsElement: <IDataElement>{
                    type: UIDataElement,                    
                    alignSelf: AlignSelf.topLeft,/**Выравнивание не только по горизонтали, но и по вертикали*/
                    // justifyContent: JustifyContent.left,
                    bindingProperty: 'name'
                },
                size:'40%'/**Ширина колонки*/
            }, {
                header: "Пол",
                justifyContent: JustifyContent.center,
                itemsElement: <IDataElement>{
                    type: UIDataElement,
                    alignSelf: AlignSelf.topCenter,/**Выравнивание не только по горизонтали, но и по вертикали*/
                    // justifyContent: JustifyContent.center,
                    bindingProperty: 'sex'
                },
                size:'30%'/**Ширина колонки*/
            }, {
                header: "Возраст",
                justifyContent: JustifyContent.right,
                itemsElement: <IDataElement>{
                    type: UIDataElement,                    
                    alignSelf: AlignSelf.topCenter,/**Выравнивание не только по горизонтали, но и по вертикали*/
                    // justifyContent: JustifyContent.center,
                    bindingProperty: 'age'
                },
                size:'30%'/**Ширина колонки*/
            }],
            //value: undefined,
            bindingProperty: 'tableData', 
            bordered: true,
            tabindex: 0,
            async onAfterAddRow(event:UIRowEvent, form, elem:ITable) {
                let elems = event.row.elements;
                let rowIndex:number = elem.rows.findIndex(row=>{return row==event.row});
                elems.forEach((elem, index)=>{
                    elem.name = `${rowIndex}-${index}`;
                    assignListeners(`       Cell ${elem.name}:`,elem);
                })
            },
            async onAfterLoad(event, form, elem) {
                assignListeners('   Table:',elem);
            },
        }
    ],
    async onAfterLoad(event, form, elem) {
        assignListeners('Form:', elem);
    },
}

let data = {
    tableData: [
        {
            age:"29",
            name:"Михаил", 
            sex:"м" 
        },
        {
            sex: "м", 
            age:"26",
            name:"Дмитрий"
        },
        {
            name: "Анна", 
            age:"20",
            sex:"ж" 
        },
    ],
    anotherData: {}
}

function assignListeners(prefix:string, elem:IElement){
    elem.on('beforeEdit', async function(event:UIEditEvent, form:IForm, elem: IDataElement, item:IDataElement){
        console.log(`%c ${prefix} beforeEdit called`, 'color: yellow');
    });
    elem.on('afterEdit', async function(event:UIEditEvent, form:IForm, elem: IDataElement, item:IDataElement){
        console.log(`%c ${prefix} onAfterEdit called`, 'color: yellow');
    });

    elem.on('focus', async function(event:UIFocusEvent, form:IForm, elem: IDataElement, item:IDataElement){
        console.log(`%c ${prefix} onFocusCapturing called`, 'color: green');
    });
    elem.on('blur',  async function(event:UIFocusEvent, form:IForm, elem: IDataElement, item:IDataElement){
        console.log(`%c ${prefix} onBlurCapturing called`, 'color: lightgreen');
    });
    elem.on('focus', async function(event:UIFocusEvent, form:IForm, elem: IDataElement, item:IDataElement){
        console.log(`%c ${prefix} onFocusBubbling called`, 'color: green');
    }, {capture:false});
    elem.on('blur',  async function(event:UIFocusEvent, form:IForm, elem: IDataElement, item:IDataElement){
        console.log(`%c ${prefix} onBlurBubbling called`, 'color: lightgreen');
    }, {capture:false});

    elem.on('keydown', async function(event:UIKeyboardEvent, form:IForm, elem: IDataElement, item:IDataElement){
        console.log(`%c ${prefix} onKeyDownCapturing called`, 'color: lightgrey');
    });
    elem.on('keyup', async function(event:UIKeyboardEvent, form:IForm, elem: IDataElement, item:IDataElement){
        console.log(`%c ${prefix} onKeyUpCapturing called`, 'color: grey');
    });
    elem.on('keydown', async function(event:UIKeyboardEvent, form:IForm, elem: IDataElement, item:IDataElement){
        console.log(`%c ${prefix} onKeyDownBubbling called`, 'color: lightgrey');
    }, {capture:false});
    elem.on('keyup', async function(event:UIKeyboardEvent, form:IForm, elem: IDataElement, item:IDataElement){
        console.log(`%c ${prefix} onKeyUpBubbling called`, 'color: grey');
    }, {capture:false})
}

/*Инициализация приложения AppManager*/
var Global: any = window;
Global.AppManager = AppManager;
Global.onpopstate = AppManager.onPopState;

AppManager.init(document.querySelector('#app'))
    .then(async ()=>{
        AppManager.add([form]);
        AppManager.open('simpleForm', data);
    })

Навигация между элементами осуществляется клавишами Tab и Shift+Tab.

Навигация между ячейками таблицы осуществляется стрелками.

Клавишей F12 откройте окно разработчика в браузере и наблюдайте за происходящими на форме событиями.

Generated using TypeDoc