Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Neos.Fusion.Form - NeosConference 2021 online

Sitegeist
May 08, 2021
100

Neos.Fusion.Form - NeosConference 2021 online

Sitegeist

May 08, 2021
Tweet

Transcript

  1. Real Values. Form: Basic ingredients • Specify target • Render

    controls • And labels • Configure Data to modify • Map data to controls • Hidden object identifiers • Hidden CSRF Token • Hidden Trusted Properties Token • Hidden Referrer • Rerender submitted values • Render validation errors 🍳
  2. Real Values. Form: Basic ingredients • Specify target • Render

    controls • And labels • Configure Data to modify • Map data to controls • Hidden object identifiers • Hidden CSRF Token • Hidden Trusted Properties Token • Hidden Referrer • Rerender submitted values • Render validation errors 🍳 Happens automagically
  3. Real Values. Fluid vs. AFX <f:form action="save" object="{customer}" objectName="{customer}" >

    <f:form.textfield property="name" /> </f:form> <Neos.Fusion.Form:Form form.target.action="save" form.data.customer={customer}> <Neos.Fusion.Form:Textfield name="customer[name]" /> </Neos.Fusion.Form:Form>
  4. Real Values. Nested api, 3 main properties • form *

    define the magic • attributes * set attributes directly • content form body - Fusion / AFX * nested properties
  5. Real Values. Generic data binding! <Neos.Fusion.Form:Form form.data.customer={customer} form.data.address={address} > <Neos.Fusion.Form:Input

    field.name="customer[name]" /> <Neos.Fusion.Form:Input field.name="address[street]" /> </Neos.Fusion.Form:Form>
  6. Real Values. Label and Message Containers <Neos.Fusion.Form:FieldContainer field.name="customer[gender]" label="Gender" >

    <Neos.Fusion.Form:Radio field.value="mr" /> <Neos.Fusion.Form:Radio field.value="mrs" /> <Neos.Fusion.Form:Radio field.value="unicorn" /> </Neos.Fusion.Form:FieldContainer>
  7. Real Values. Fusion.Form Rendering - New features • Fusion Controller

    forms • Fusion Flow projects • Fusion Neos Backend Modules • Neos Login Screen & History Module • Forms as presentational Fusion
  8. Real Values. 1. renderer = Neos.Fusion.Form:Runtime.RuntimeForm { 2. # the

    form argument namespace 3. namespace = 'example' 4. 5. # initial form data to prefill the fields 6. data = Neos.Fusion:DataStructure 7. 8. # the form process for rendering and validation 9. process = Neos.Fusion.Form:Runtime.SingleStepProcess 10. 11. # action after the process is finished 12. action = Neos.Fusion.Form:Runtime.Actions 13. } Runtime.Form
  9. Real Values. Runtime.Form - Process 1. Take initial data 2.

    handle submitted Data 3. Is the process finished? a. Return final data to perform action b. Render form with validation results Action Final data Initial data Submitted data
  10. Real Values. 1. process = Neos.Fusion.Form:Runtime.SingleStepProcess { 2. content =

    afx` 3. <Neos.Fusion.Form:FieldContainer field.name="firstName" label="First Nam 4. <Neos.Fusion.Form:Input /> 5. </Neos.Fusion.Form:FieldContainer> 6. <Neos.Fusion.Form:FieldContainer field.name="lastName" label="Last Name 7. <Neos.Fusion.Form:Input /> 8. </Neos.Fusion.Form:FieldContainer> 9. ` 10. schema { 11. firstName = ${Form.Schema.string().isRequired()} 12. lastName = ${Form.Schema.string().isRequired()} 13. } 14. footer = afx` 15. <button type="submit" class="btn btn-primary">Submit</button> 16. ` 17. } Runtime.Form - SingleStepProcess
  11. Real Values. 1.action { 2. redirect { 3. type =

    'Neos.Fusion.Form.Runtime:Redirect' 4. options.uri = Neos.Neos:NodeUri { 5. node = ${q(node).property('redirectTarget')} 6. } 7. } 8. 9. email { 10. @if.has = ${q(node).property('mailTo')} 11. type = 'Neos.Fusion.Form.Runtime:Email' 12. options { 13. senderAddress = ${q(node).property('mailFrom')} 14. recipientAddress = ${q(node).property('mailTo')} 15. subject = ${q(node).property('mailSubject')} html = afx`<h1>Thank you {data.firstName} >from {data.city}, {data.street}</p>` Runtime.Form - Action
  12. Real Values. Action Final data a Step 1 Step 2

    Confirm Runtime.Form - MultiStepProcess
  13. Real Values. 1.renderer = Neos.Fusion.Form:Runtime.RuntimeForm { 2. 3. process =

    Neos.Fusion.Form:Runtime.MultiStepProcess { 4. steps { 5. first { 6. content = ... 7. schema = ... 8. } 9. second { 10. content = ... 11. schema = ... 12. } 13. confirm { 14. content = ... 15. } 16. } 17. } Runtime.Form - Multi Step Process
  14. Real Values. Fusion.Form Runtime - New features • AFX for

    content • Access node properties • Access settings • Use @if conditions • Fusion reusability • Migrate Runtime Forms -> Controller Forms • Presentational Fusion / Styleguide support
  15. Real Values. Fusion.Form - Extensibility • Custom Rendering ◦ FieldTypes

    -> Fusion ◦ Label and ErrorRenderer -> Fusion ◦ FieldContainers -> Fusion • Runtime Interfaces ◦ ActionInterface (formerly known as Finisher) ◦ Process- & SchemaInterface ◦ ProcessCollectionInterface • Flow ValidatorInterface
  16. Real Values. ## # "ContactForm" element # prototype(Neos.Demo:Content.ContactForm) < prototype(Neos.Neos:ContentComponent)

    { renderer = Neos.Fusion.Form:Runtime.RuntimeForm { namespace = 'contact' process { content = afx` <fieldset> <legend>Contact</legend> <Neos.Fusion.Form:FieldContainer label="Name" field.name="name"> <div class="input"> <Neos.Fusion.Form:Input attributes.class="form-control" /> </div> </Neos.Fusion.Form:FieldContainer> <Neos.Fusion.Form:FieldContainer label="Email" field.name="email"> <div class="input"> <Neos.Fusion.Form:Input attributes.class="form-control" /> </div> </Neos.Fusion.Form:FieldContainer> .Form:FieldContainer label="Message" field.name="message"> class="form-control" /> Example - ContactForm
  17. Real Values. Example - ContactForm ## # "ContactForm" ele #

    prototype(Neos.Demo:Content.ContactForm) < prototype renderer = Neos.Fusion.Form:Runtime.RuntimeForm { namespace = 'contact' process { content = afx` <fieldset> <legend>Contact</legend> <Neos.Fusion.Form:FieldContainer label="Name" field.name="name"> <div class="input"> <Neos.Fusion.Form:Input attributes.class="form-control" /> </div> </Neos.Fusion.Form:FieldContainer> <Neos.Fusion.Form:FieldContainer label="Email" field.name="email"> <div class="input"> <Neos.Fusion.Form:Input attributes.class="form-control" /> </div> </Neos.Fusion.Form:FieldContainer> <Neos.Fusion.Form:FieldContainer label="Message" field.name="message"> <div class="input"> <Neos.Fusion.Form:Textarea attributes.class="form-control" /> </div> </Neos.Fusion.Form:FieldContainer> </fieldset> ` footer = afx` <button type="submit" class="btn btn-primary">Submit</button> ')}
  18. Real Values. Example - ContactForm <Neos.Fusion.For <div class="input"> <Neos.Fusion.Form:Textarea attributes.cla

    </div> </Neos.Fusion.Form:FieldContainer> </fieldset> ` footer = afx` <button type="submit" class="btn btn-primary">Submit</button> ` schema { name = ${Form.Schema.string().isRequired()} email = ${Form.Schema.string().isRequired().validator('EmailAddress')} message = ${Form.Schema.string().isRequired()} } } action { message { type = 'Neos.Fusion.Form.Runtime:Message' options.message = ${q(node).property('message')} } email { @if.has = ${q(node).property('subject') && q(node).property('recipientAddress') type = 'Neos.Fusion.Form.Runtime:Email' options { recipientName = ${q(node).property('recipientName')} ss = ${q(node).property('recipientAddress')} y('senderName')} ss')}
  19. Real Values. Example - ContactForm } action { message {

    type = 'Neos.Fusion.Form.Runtime:Message' options.message = ${q(node).property('message')} } email { @if.has = ${q(node).property('subject') && q(node).property('recipientAddress') && q( type = 'Neos.Fusion.Form.Runtime:Email' options { recipientName = ${q(node).property('recipientName')} recipientAddress = ${q(node).property('recipientAddress')} senderName = ${q(node).property('senderName')} senderAddress = ${q(node).property('senderAddress')} subject = ${q(node).property('subject')} replyToAddress = ${data.email} html = afx` <p>Message from {data.name}</p> <p>{data.message}</p> ` } } redirect { @if.has = ${q(node).property('redirect')} type = 'Neos.Fusion.Form.Runtime:Redirect' options.uri = Neos.Neos:NodeUri { node = ${q(node).property('redirect')}
  20. Real Values. Fusion.Form Runtime - Ideas for you • ReCaptcha

    integration • Newsletter subscription action • Persistence action • Node based forms • Custom processes
  21. Real Values. Requirements • Form Rendering ◦ Neos.Fusion.Form > 1.0

    ◦ Neos > 4.3 • Form Runtime ◦ Neos.Fusion.Form > 2.0 ◦ Neos > 5.0
  22. Real Values. Fusion.Form Runtime - Docs & Help • Package

    Readme https://github.com/neos/fusion-form • Neos Demo https://github.com/neos/Neos.Demo • Neos Slack #project-fusion-form / #neos-general
  23. Real Values. Fusion.Form Runtime - Pitfalls • Brand new …

    bugs included ◦ less code, less places to hide ◦ minimalistic core • Testing Fusion is hard ◦ Unit & Functional Tests ◦ Static Analysis ◦ No end to end tests -YET
  24. Real Values. Fusion.Form Runtime - Future • New versions of

    Fusion Form • Public Packages with Actions and FieldTypes • Node based Fusion.Form.Builder • Move into neos-development-collection • Neos CMS usable without Fluid • Fluid will stay - as an option • Yaml Forms will stay aswell