Mark required fields in output when using form builder (#3296)
authorMatthias Schmidt <gravatronics@live.com>
Thu, 21 May 2020 18:18:38 +0000 (20:18 +0200)
committerGitHub <noreply@github.com>
Thu, 21 May 2020 18:18:38 +0000 (20:18 +0200)
Close #3265

12 files changed:
com.woltlab.wcf/templates/__form.tpl
com.woltlab.wcf/templates/__formContainer.tpl
com.woltlab.wcf/templates/__formField.tpl
wcfsetup/install/files/acp/templates/__form.tpl
wcfsetup/install/files/acp/templates/__formContainer.tpl
wcfsetup/install/files/acp/templates/__formField.tpl
wcfsetup/install/files/lib/system/form/builder/FormDocument.class.php
wcfsetup/install/files/lib/system/form/builder/IFormDocument.class.php
wcfsetup/install/files/lib/system/form/builder/container/FormContainer.class.php
wcfsetup/install/files/lib/system/form/builder/container/IFormContainer.class.php
wcfsetup/install/files/lib/system/form/builder/container/wysiwyg/WysiwygFormContainer.class.php
wcfsetup/install/files/style/layout/form.scss

index 8719c7e04b314e89bf4813d64be5fe80a9ef11bf..d6ad54d0e6734b2f878fc27a813382009202a20e 100644 (file)
        </form>
 {/if}
 
+{if $form->needsRequiredFieldsInfo()}
+       <div class="section requiredFieldsInfo">
+               <p><span class="formFieldRequired">*</span> {lang}wcf.global.form.required{/lang}</p>
+               
+               {event name='requiredFieldsInfo'}
+       </div>
+{/if}
+
 <script data-relocate="true">
        {* after all dependencies have been added, check them *}
        require(['WoltLabSuite/Core/Form/Builder/Field/Dependency/Manager'], function(FormBuilderFieldDependencyManager) {
index eec1c6606bafb02b1a7f00040ff9c4a65e161d2b..b7ff418e62a84edc09bac06d4757d816b50fca80 100644 (file)
@@ -6,11 +6,11 @@
        {if $container->getLabel() !== null}
                {if $container->getDescription() !== null}
                        <header class="sectionHeader">
-                               <h2 class="sectionTitle">{@$container->getLabel()}</h2>
+                               <h2 class="sectionTitle">{@$container->getLabel()}{if $container->markAsRequired()} <span class="formFieldRequired">*</span>{/if}</h2>
                                <p class="sectionDescription">{@$container->getDescription()}</p>
                        </header>
                {else}
-                       <h2 class="sectionTitle">{@$container->getLabel()}</h2>
+                       <h2 class="sectionTitle">{@$container->getLabel()}{if $container->markAsRequired()} <span class="formFieldRequired">*</span>{/if}</h2>
                {/if}
        {/if}
        
index d726d5aa69c0a87177d92d03f6dfccc1cdc2ee60..d59c467b7d915a33579687c696fa057fa9ffdf5f 100644 (file)
@@ -1,5 +1,5 @@
 <dl id="{@$field->getPrefixedId()}Container" {if !$field->getClasses()|empty} class="{implode from=$field->getClasses() item='class' glue=' '}{$class}{/implode}"{/if}{foreach from=$field->getAttributes() key='attributeName' item='attributeValue'} {$attributeName}="{$attributeValue}"{/foreach}{if !$field->checkDependencies()} style="display: none;"{/if}>
-       <dt>{if $field->getLabel() !== null}<label for="{@$field->getPrefixedId()}">{@$field->getLabel()}</label>{/if}</dt>
+       <dt>{if $field->getLabel() !== null}<label for="{@$field->getPrefixedId()}">{@$field->getLabel()}</label>{if $field->isRequired()} <span class="formFieldRequired">*</span>{/if}{/if}</dt>
        <dd>
                {@$field->getFieldHtml()}
                
index 8719c7e04b314e89bf4813d64be5fe80a9ef11bf..d6ad54d0e6734b2f878fc27a813382009202a20e 100644 (file)
        </form>
 {/if}
 
+{if $form->needsRequiredFieldsInfo()}
+       <div class="section requiredFieldsInfo">
+               <p><span class="formFieldRequired">*</span> {lang}wcf.global.form.required{/lang}</p>
+               
+               {event name='requiredFieldsInfo'}
+       </div>
+{/if}
+
 <script data-relocate="true">
        {* after all dependencies have been added, check them *}
        require(['WoltLabSuite/Core/Form/Builder/Field/Dependency/Manager'], function(FormBuilderFieldDependencyManager) {
index eec1c6606bafb02b1a7f00040ff9c4a65e161d2b..b7ff418e62a84edc09bac06d4757d816b50fca80 100644 (file)
@@ -6,11 +6,11 @@
        {if $container->getLabel() !== null}
                {if $container->getDescription() !== null}
                        <header class="sectionHeader">
-                               <h2 class="sectionTitle">{@$container->getLabel()}</h2>
+                               <h2 class="sectionTitle">{@$container->getLabel()}{if $container->markAsRequired()} <span class="formFieldRequired">*</span>{/if}</h2>
                                <p class="sectionDescription">{@$container->getDescription()}</p>
                        </header>
                {else}
-                       <h2 class="sectionTitle">{@$container->getLabel()}</h2>
+                       <h2 class="sectionTitle">{@$container->getLabel()}{if $container->markAsRequired()} <span class="formFieldRequired">*</span>{/if}</h2>
                {/if}
        {/if}
        
index d726d5aa69c0a87177d92d03f6dfccc1cdc2ee60..d59c467b7d915a33579687c696fa057fa9ffdf5f 100644 (file)
@@ -1,5 +1,5 @@
 <dl id="{@$field->getPrefixedId()}Container" {if !$field->getClasses()|empty} class="{implode from=$field->getClasses() item='class' glue=' '}{$class}{/implode}"{/if}{foreach from=$field->getAttributes() key='attributeName' item='attributeValue'} {$attributeName}="{$attributeValue}"{/foreach}{if !$field->checkDependencies()} style="display: none;"{/if}>
-       <dt>{if $field->getLabel() !== null}<label for="{@$field->getPrefixedId()}">{@$field->getLabel()}</label>{/if}</dt>
+       <dt>{if $field->getLabel() !== null}<label for="{@$field->getPrefixedId()}">{@$field->getLabel()}</label>{if $field->isRequired()} <span class="formFieldRequired">*</span>{/if}{/if}</dt>
        <dd>
                {@$field->getFieldHtml()}
                
index 8fe3d7a93d0a0063a54ab6822b87c6509759c6ed..88308ebbe7ea19bffaf395907926bf1d1318a0eb 100644 (file)
@@ -527,6 +527,29 @@ class FormDocument implements IFormDocument {
                return $this->invalid;
        }
        
+       /**
+        * @inheritDoc
+        * @since       5.3
+        */
+       public function needsRequiredFieldsInfo() {
+               /** @var IFormNode $node */
+               foreach ($this->getIterator() as $node) {
+                       if (
+                               $node->isAvailable()
+                               && $node instanceof IFormElement
+                               && $node->getLabel() !== null
+                               && (
+                                       ($node instanceof IFormContainer && $node->markAsRequired())
+                                       || ($node instanceof IFormField && $node->isRequired())
+                               )
+                       ) {
+                               return true;
+                       }
+               }
+
+               return false;
+       }
+       
        /**
         * @inheritDoc
         */
index 7025fc9495d3cef6b96627d9003c2c54d7d2edb4..6009d40b2d5d1b5fe1f7e0e52db96f206c928936 100644 (file)
@@ -287,6 +287,14 @@ interface IFormDocument extends IFormParentNode {
         */
        public function invalid($invalid = true);
        
+       /**
+        * Returns `true` if the information about required fields has to be shown below the form.
+        * 
+        * @return      bool
+        * @since       5.3
+        */
+       public function needsRequiredFieldsInfo();
+       
        /**
         * Sets the updated object (and loads the field values from the given object) and returns
         * this document.
index 008a3cda3b448a7c9fe825e9c01587aac2fa7f88..ef92e4140d400d63a4c63c64b1c159de89fdf5fe 100644 (file)
@@ -58,6 +58,14 @@ class FormContainer implements IFormContainer {
                );
        }
        
+       /**
+        * @inheritDoc
+        * @since       5.3
+        */
+       public function markAsRequired() {
+               return false;
+       }
+       
        /**
         * @inheritDoc
         */
index efdbbb942005547009438ebbe903122d96de2517..e654776f28d964340cd6fd23834ef74848de86af 100644 (file)
@@ -15,6 +15,14 @@ use wcf\system\form\builder\IFormParentNode;
  * @since      5.2
  */
 interface IFormContainer extends IFormChildNode, IFormElement, IFormParentNode {
+       /**
+        * Returns `true` if the whole container should be marked as required in the form output.
+        * 
+        * @return      bool
+        * @since       5.3
+        */
+       public function markAsRequired();
+       
        /**
         * Informs the form container of the updated object and this method is called by
         * `IFormDocument::updatedObject()` to inform the container that object data is being loaded.
index 51c645528c77ff0bc152f29a7580db180e2cd948..c90f89314d2b7b72607e23b4706a667f6c348b97 100644 (file)
@@ -316,6 +316,14 @@ class WysiwygFormContainer extends FormContainer {
                return $this->required;
        }
        
+       /**
+        * @since       5.3
+        * @inheritDoc
+        */
+       public function markAsRequired() {
+               return $this->getWysiwygField()->isRequired();
+       }
+       
        /**
         * Sets the message object type used by the wysiwyg form field.
         * 
index 29dc64b66c5d161e28c091e5b86d5779f87e9c84..50d1f391819fa862198a693c833d706b277d4c38 100644 (file)
@@ -279,6 +279,7 @@ input {
        }
 }
 
+.formFieldRequired,
 .customOptionRequired {
        color: rgba(204, 0, 1, 1) !important;
 }