{"id":15025780,"url":"https://github.com/dmvdbrugge/dynamic-components","last_synced_at":"2025-04-09T20:04:43.468Z","repository":{"id":56970324,"uuid":"137575260","full_name":"dmvdbrugge/dynamic-components","owner":"dmvdbrugge","description":"Dynamic Components for the PHP UI extension","archived":false,"fork":false,"pushed_at":"2019-05-10T09:40:35.000Z","size":70,"stargazers_count":6,"open_issues_count":3,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-09T20:04:36.075Z","etag":null,"topics":["callbacks","components","dynamic","php","php-ui","php7","php71"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dmvdbrugge.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-06-16T11:20:32.000Z","updated_at":"2024-01-18T03:43:25.000Z","dependencies_parsed_at":"2022-08-21T06:40:19.876Z","dependency_job_id":null,"html_url":"https://github.com/dmvdbrugge/dynamic-components","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dmvdbrugge%2Fdynamic-components","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dmvdbrugge%2Fdynamic-components/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dmvdbrugge%2Fdynamic-components/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dmvdbrugge%2Fdynamic-components/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dmvdbrugge","download_url":"https://codeload.github.com/dmvdbrugge/dynamic-components/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248103868,"owners_count":21048245,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["callbacks","components","dynamic","php","php-ui","php7","php71"],"created_at":"2024-09-24T20:03:00.242Z","updated_at":"2025-04-09T20:04:43.447Z","avatar_url":"https://github.com/dmvdbrugge.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Dynamic Components\nDynamic Components for the PHP UI extension: use callbacks instead of hardcoded actions. Features advanced versions of\nthe basic controls provided by the extension.\n\n[![Build Status](https://travis-ci.org/dmvdbrugge/dynamic-components.svg?branch=master)](https://travis-ci.org/dmvdbrugge/dynamic-components)\n\n## Usage / Examples\n\nThe most basic example is a button that changes its text when clicked:\n\n```php\n\u003c?php\n\nuse DynamicComponents\\Controls\\Button;\n\n$button = new Button('Click me!', function (Button $button) {\n    $button-\u003esetText('You clicked :D');\n});\n```\n\nThis in contrast to having to create a hardcoded or anonymous class:\n\n```php\n\u003c?php\n\nuse UI\\Controls\\Button;\n\n$button = new class('Click me!') extends Button {\n    protected function onClicked(): void\n    {\n        $this-\u003esetText('You clicked :D');\n    }\n};\n```\n\nWhen we take the first example a bit further, say we now want 3 buttons:\n\n```php\n\u003c?php\n\nuse DynamicComponents\\Controls\\Button;\n\n$onClick = function (Button $button) {\n    $button-\u003esetText('You clicked :D');\n};\n\n$button1 = new Button('Click me!', $onClick);\n$button2 = new Button('Click me!', $onClick);\n$button3 = new Button('Click me!', $onClick);\n```\n\nWhereas in the `extends` form you either need to duplicate the anonymous class multiple times (duplicating logic), or\ncreate an actual class (which gives you some additional options, but also more hassle).\n\nEach callback will receive the component that the action triggers for as last parameter. Last mostly means only (and\nthus also first), but is relevant for `Area`'s actions, as they receive multiple params already.\n\nSee also the [examples](examples), which feature several Controls used in different ways and coding styles. Every\nexample is a fully working program and can be run directly with php, given of course the extension is enabled. See also\n[csv2qif](https://github.com/dmvdbrugge/csv2qif)'s\n[FileSelect](https://github.com/dmvdbrugge/csv2qif/blob/master/src/UiComponents/FileSelect.php) for a more advanced\nversion of the filepicker. (Or any of its other `UiComponents`. It's kicked off in `src/Command/Ui.php` but that's the\nboring part.)\n\n## API\n\nAll components extend a class, usually the one provided by the extension. Inherited methods are unlisted but obviously\nstill available. All component descriptions in this section are in the same format:\n\n[`Clickable FQN (is link to source)`](src)` extends `[`Clickable FQN (is link to its API docs)`](#api)\n```php\n// Constructor\n\n// Relevant overridden methods, if any\n\n// Additional methods\n```\n\nExtra information, if any.\n\n### Controls\n\n#### Button\n[`DynamicComponents\\Controls\\Button`](src/Controls/Button.php)` extends `[`UI\\Controls\\Button`](https://secure.php.net/manual/en/class.ui-controls-button.php)\n```php\n// Constructor\npublic function __construct(string $text, ?callable $onClick = null)\n\n// Additional methods\npublic function setOnClick(callable $onClick): void\n```\n\n#### Check\n[`DynamicComponents\\Controls\\Check`](src/Controls/Check.php)` extends `[`UI\\Controls\\Check`](https://secure.php.net/manual/en/class.ui-controls-check.php)\n```php\n// Constructor\npublic function __construct(string $text, ?callable $onToggle = null, bool $checked = false)\n\n// Additional methods\npublic function setOnToggle(callable $onToggle): void\n```\n\n#### ColorButton\n[`DynamicComponents\\Controls\\ColorButton`](src/Controls/ColorButton.php)` extends `[`UI\\Controls\\ColorButton`](https://secure.php.net/manual/en/class.ui-controls-colorbutton.php)\n```php\n// Constructor\npublic function __construct(?callable $onChange = null, ?Color $color = null)\n\n// Additional methods\npublic function setOnChange(callable $onChange): void\n```\n\n#### Combo\n[`DynamicComponents\\Controls\\Combo`](src/Controls/Combo.php)` extends `[`UI\\Controls\\Combo`](https://secure.php.net/manual/en/class.ui-controls-combo.php)\n```php\n// Constructor\npublic function __construct(?callable $onSelected = null)\n\n// Additional methods\npublic function setOnSelected(callable $onSelected): void\n```\n\n#### EditableCombo\n[`DynamicComponents\\Controls\\EditableCombo`](src/Controls/EditableCombo.php)` extends `[`UI\\Controls\\EditableCombo`](https://secure.php.net/manual/en/class.ui-controls-editablecombo.php)\n```php\n// Constructor\npublic function __construct(?callable $onChange = null, string $text = '')\n\n// Additional methods\npublic function setOnChange(callable $onChange): void\n```\n\n#### Entry\n[`DynamicComponents\\Controls\\Entry`](src/Controls/Entry.php)` extends `[`UI\\Controls\\Entry`](https://secure.php.net/manual/en/class.ui-controls-entry.php)\n```php\n// Constructor\npublic function __construct(int $type = Entry::Normal, ?callable $onChange = null, string $text = '', bool $readOnly = false)\n\n// Additional methods\npublic function getType(): int\npublic function setOnChange(callable $onChange): void\n```\n\n#### MultilineEntry\n[`DynamicComponents\\Controls\\MultilineEntry`](src/Controls/MultilineEntry.php)` extends `[`UI\\Controls\\MultilineEntry`](https://secure.php.net/manual/en/class.ui-controls-multilineentry.php)\n```php\n// Constructor\npublic function __construct(int $type = MultilineEntry::Wrap, ?callable $onChange = null, string $text = '', bool $readOnly = false)\n\n// Additional methods\npublic function getType(): int\npublic function setOnChange(callable $onChange): void\n```\n\n#### Radio\n[`DynamicComponents\\Controls\\Radio`](src/Controls/Radio.php)` extends `[`UI\\Controls\\Radio`](https://secure.php.net/manual/en/class.ui-controls-radio.php)\n```php\n// Constructor\npublic function __construct(?callable $onSelected = null)\n\n// Additional methods\npublic function setOnSelected(callable $onSelected): void\n```\n\n#### Slider\n[`DynamicComponents\\Controls\\Slider`](src/Controls/Slider.php)` extends `[`UI\\Controls\\Slider`](https://secure.php.net/manual/en/class.ui-controls-slider.php)\n```php\n// Constructor\npublic function __construct(int $min, int $max, ?callable $onChange = null, ?int $value = null)\n\n// Additional methods\npublic function getMax(): int\npublic function getMin(): int\npublic function setOnChange(callable $onChange): void\n```\n\nBecause `UI\\Controls\\Slider` accepts `$min \u003e $max` and then flips them, so does `DynamicComponents\\Controls\\Slider`.\nHowever for clarity's sake you should pass them in the correct way, as the getters return the actual min and max.\n\n#### Spin\n[`DynamicComponents\\Controls\\Spin`](src/Controls/Spin.php)` extends `[`UI\\Controls\\Spin`](https://secure.php.net/manual/en/class.ui-controls-spin.php)\n```php\n// Constructor\npublic function __construct(int $min, int $max, ?callable $onChange = null, ?int $value = null)\n\n// Additional methods\npublic function getMax(): int\npublic function getMin(): int\npublic function setOnChange(callable $onChange): void\n```\n\nBecause `UI\\Controls\\Spin` accepts `$min \u003e $max` and then flips them, so does `DynamicComponents\\Controls\\Spin`.\nHowever for clarity's sake you should pass them in the correct way, as the getters return the actual min and max.\n\n### Advanced Controls\n\n#### Combo\n[`DynamicComponents\\AdvancedControls\\Combo`](src/AdvancedControls/Combo.php)` extends `[`DynamicComponents\\Controls\\Combo`](#combo)\n```php\n// Constructor\npublic function __construct(string[] $options, ?callable $onSelected = null, int|string $selected = 0)\n\n// Additional methods\npublic function appendAll(string[] $options): void\npublic function getOptions(): string[]\npublic function getSelectedText(): string\npublic function setSelectedText(string $text): void\n```\n\n#### Radio\n[`DynamicComponents\\AdvancedControls\\Radio`](src/AdvancedControls/Radio.php)` extends `[`DynamicComponents\\Controls\\Radio`](#radio)\n```php\n// Constructor\npublic function __construct(string[] $options, ?callable $onSelected = null, int|string $selected = -1)\n\n// Additional methods\npublic function appendAll(string[] $options): void\npublic function getOptions(): string[]\npublic function getSelectedText(): string\npublic function setSelectedText(string $text): void\n```\n\n### Other\n\n#### Area\n[`DynamicComponents\\Area`](src/Area.php)` extends `[`UI\\Area`](https://secure.php.net/manual/en/class.ui-area.php)\n```php\n// Constructor\npublic function __construct(?callable $onDraw = null, ?callable $onKey = null, ?callable $onMouse = null)\n\n// Additional methods\npublic function setOnDraw(callable $onDraw): void\npublic function setOnKey(callable $onKey): void\npublic function setOnMouse(callable $onMouse): void\n```\n\n#### Executor\n[`DynamicComponents\\Executor`](src/Executor.php)` extends `[`UI\\Executor`](https://secure.php.net/manual/en/class.ui-executor.php)\n```php\n// Constructor\npublic function __construct(int $seconds = 0, ?int $microseconds = null, ?callable $onExecute = null)\n\n// Additional methods\npublic function getInterval(): int[]\npublic function setOnExecute(callable $onExecute): void\n```\n\n#### Menu\n[`DynamicComponents\\Menu`](src/Menu.php)` extends `[`UI\\Menu`](https://secure.php.net/manual/en/class.ui-menu.php)\n```php\n// Constructor\npublic function __construct(string $name)\n\n// Relevant override (default param changes)\npublic function append(string $name, string $type = \\DynamicComponents\\MenuItem::class): \\UI\\MenuItem\n\n// Additional methods\npublic function add(string $name): \\DynamicComponents\\MenuItem\npublic function addAs(string $type, string $name): \\UI\\MenuItem\npublic function getName(): string\npublic function getMenuItemName(\\UI\\MenuItem $menuItem): string\npublic function hasMenuItem(\\UI\\MenuItem $menuItem): bool\n```\n\n`Menu` has no actions itself, but is used for creating `MenuItem`s. While `DynamicComponents\\MenuItem`s can be used\nwith a `UI\\Menu`, using a `DynamicComponents\\Menu` has the following advantages: it adds itself as parent, it sets the\n`MenuItem`'s name, and it has `DynamicComponents\\MenuItem` as default in `append()`. It's fully backwards compatible\nthough, so you can still create `UI\\MenuItem`s with it.\n\nTo facilitate both stricter typing and supporting PhpStorm's Advanced Metadata, `add()` has been added as correctly\ntyped shortcut, together with `addAs()` which has arguments flipped compared to `append()` for type detection (which\nonly works on the first param).\n\n#### MenuItem\n[`DynamicComponents\\MenuItem`](src/MenuItem.php)` extends `[`UI\\MenuItem`](https://secure.php.net/manual/en/class.ui-menuitem.php)\n```php\n// No constructor, MenuItems are created by a Menu via append()\n\n// Additional methods\npublic function getName(): ?string\npublic function getParent(): \\DynamicComponents\\Menu\npublic function isEnabled(): bool\npublic function setOnClick(callable $onClick): void\n```\n\nName and Parent are only available when created by a `DynamicComponents\\Menu`. Theoretically, name could be set\nmanually, but there is no guarantee that it's actually correct.\n\n#### Window\n[`DynamicComponents\\Window`](src/Window.php)` extends `[`UI\\Window`](https://secure.php.net/manual/en/class.ui-window.php)\n```php\n// Constructor\npublic function __construct(string $title, \\UI\\Size $size, bool $menu = false, ?callable $onClosing = null)\n\n// Additional methods\npublic function hasMenu(): bool\npublic function setOnClosing(callable $onClosing): void\n```\n\nThe default action on a `UI\\Window` without `onClosing` is to `destroy()` itself and call `UI\\quit()`. To provide the\nsame functionality in a flexible way `DynamicComponents\\Window` does this as well, but you can prevent it by returning\n`false` from the callback.\n\n## Installation\nDynamic Components is just a single composer call away:\n```\ncomposer require dmvdbrugge/dynamic-components\n```\n\n## Background\n[csv2qif](https://github.com/dmvdbrugge/csv2qif) was a happy little commandline tool, until I stumbled upon the\n[PHP UI extension](https://secure.php.net/manual/en/book.ui.php) ([source](https://github.com/krakjoe/ui)). Coming from\na web-background, where callbacks are flowing freely, the idea of hardcoding every button, dropdown, and radio was not a\npleasant one. Thus the dynamic button was born, quickly followed by the advanced controls combo and radio.\n\nRealizing this had nothing to do with the tool itself, the idea sparked to move them to a library of their own,\nproviding a reason to let their actionable control-friends (check, entry, etc.) join the party. So here we are.\n\n## License\nMIT License\n\nCopyright (c) 2018-2019 Dave van der Brugge\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdmvdbrugge%2Fdynamic-components","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdmvdbrugge%2Fdynamic-components","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdmvdbrugge%2Fdynamic-components/lists"}