|
| 1 | +.. index:: |
| 2 | + single: Create a UX bundle |
| 3 | + |
| 4 | +Create a UX bundle |
| 5 | +================== |
| 6 | + |
| 7 | +.. tip:: |
| 8 | + |
| 9 | + Before reading this, you may want to have a look at |
| 10 | + :doc:`Best Practices for Reusable Bundles </bundles/best_practices>`. |
| 11 | + |
| 12 | +Here are a few tricks to make your bundle install as a UX bundle. |
| 13 | + |
| 14 | +composer.json file |
| 15 | +------------------ |
| 16 | + |
| 17 | +Your ``composer.json`` file must have the ``symfony-ux`` keyword: |
| 18 | + |
| 19 | +.. code-block:: json |
| 20 | +
|
| 21 | + { |
| 22 | + "keywords": ["symfony-ux"] |
| 23 | + } |
| 24 | +
|
| 25 | +Assets location |
| 26 | +--------------- |
| 27 | + |
| 28 | +Your assets must be located in one of the following directories, with a ``package.json`` file so Flex can handle it |
| 29 | +during install/update: |
| 30 | + |
| 31 | +* ``/assets`` (recommended) |
| 32 | +* ``/Resources/assets`` |
| 33 | +* ``/src/Resources/assets`` |
| 34 | + |
| 35 | +package.json file |
| 36 | +----------------- |
| 37 | + |
| 38 | +Your ``package.json`` file must contain a ``symfony`` config with controllers defined, and also add required packages |
| 39 | +to the ``peerDependencies``: |
| 40 | + |
| 41 | +.. code-block:: json |
| 42 | +
|
| 43 | + { |
| 44 | + "name": "@acme/feature", |
| 45 | + "version": "1.0.0", |
| 46 | + "symfony": { |
| 47 | + "controllers": { |
| 48 | + "slug": { |
| 49 | + "main": "dist/controller.js", |
| 50 | + "fetch": "eager", |
| 51 | + "enabled": true, |
| 52 | + "autoimport": { |
| 53 | + "dist/bootstrap4-theme.css": false, |
| 54 | + "dist/bootstrap5-theme.css": true |
| 55 | + } |
| 56 | + } |
| 57 | + } |
| 58 | + }, |
| 59 | + "peerDependencies": { |
| 60 | + "@hotwired/stimulus": "^3.0.0", |
| 61 | + "slugify": "^1.6.5" |
| 62 | + } |
| 63 | + } |
| 64 | +
|
| 65 | +In this case, the file located at ``[assets directory]/dist/controller.js`` will be exposed. |
| 66 | + |
| 67 | +.. tip:: |
| 68 | + |
| 69 | + You can either write raw JS in this ``dist/controller.js`` file, or you can e.g. write your controller with |
| 70 | + TypeScript and transpile it to JavaScript. |
| 71 | + |
| 72 | + Here is an example to do so: |
| 73 | + |
| 74 | + 1. Add the following to your ``package.json`` file: |
| 75 | + |
| 76 | + .. code-block:: json |
| 77 | +
|
| 78 | + { |
| 79 | + "scripts": { |
| 80 | + "build": "babel src --extensions .ts -d dist" |
| 81 | + }, |
| 82 | + "devDependencies": { |
| 83 | + "@babel/cli": "^7.20.7", |
| 84 | + "@babel/core": "^7.20.12", |
| 85 | + "@babel/plugin-proposal-class-properties": "^7.18.6", |
| 86 | + "@babel/preset-env": "^7.20.2", |
| 87 | + "@babel/preset-typescript": "^7.18.6", |
| 88 | + "@hotwired/stimulus": "^3.2.1", |
| 89 | + "typescript": "^4.9.5" |
| 90 | + } |
| 91 | + } |
| 92 | +
|
| 93 | + 2. Run either ``npm install`` or ``yarn install`` to install the new dependencies. |
| 94 | + |
| 95 | + 3. Write your Stimulus controller with TypeScript in ``src/controller.ts``. |
| 96 | + |
| 97 | + 4. Run ``npm run build`` or ``yarn run build`` to transpile your TypeScript controller into JavaScript. |
| 98 | + |
| 99 | +To use your controller in a template (e.g. one defined in your bundle) you can use it like this: |
| 100 | + |
| 101 | +.. code-block:: html+twig |
| 102 | + |
| 103 | + <div |
| 104 | + {{ stimulus_controller('acme/feature/slug', { modal: 'my-value' }) }} |
| 105 | + {# |
| 106 | + will render: |
| 107 | + data-controller="acme--feature--slug" |
| 108 | + data-acme--feature--slug-modal-value="my-value" |
| 109 | + #} |
| 110 | + > |
| 111 | + ... |
| 112 | + </div> |
| 113 | + |
| 114 | +Don't forget to add ``symfony/webpack-encore-bundle:^1.12`` as a composer dependency to use |
| 115 | +Twig ``stimulus_*`` functions. |
| 116 | + |
| 117 | +.. tip:: |
| 118 | + |
| 119 | + Controller Naming: In this example, the ``name`` of the PHP package is ``acme/feature`` and the name |
| 120 | + of the controller in ``package.json`` is ``slug``. So, the full controller name for Stimulus will be |
| 121 | + ``acme--feature--slug``, though with the ``stimulus_controller()`` function, you can use ``acme/feature/slug``. |
| 122 | + |
| 123 | +Each controller has a number of options in ``package.json`` file: |
| 124 | + |
| 125 | +================== ==================================================================================================== |
| 126 | +Option Description |
| 127 | +================== ==================================================================================================== |
| 128 | +enabled Whether the controller should be enabled by default. |
| 129 | +main Path to the controller file. |
| 130 | +fetch How controller & dependencies are included when the page loads. |
| 131 | + Use ``eager`` (default) to make controller & dependencies included in the JavaScript that's |
| 132 | + downloaded when the page is loaded. |
| 133 | + Use ``lazy`` to make controller & dependencies isolated into a separate file and only downloaded |
| 134 | + asynchronously if (and when) the data-controller HTML appears on the page. |
| 135 | +autoimport List of files to be imported with the controller. Useful e.g. when there are several CSS styles |
| 136 | + depending on the frontend framework used (like Bootstrap 4 or 5, Tailwind CSS...). |
| 137 | + The value must be an object with files as keys, and a boolean as value for each file to set |
| 138 | + whether the file should be imported. |
| 139 | +================== ==================================================================================================== |
0 commit comments