Display Logic Module for SilverStripe 3

28 Jan

 

Hello, SilverStripers!

Have you ever had a page type or DataObject that has fields that should only be displayed if other form fields are set a certain way? Imagine an object that can take either an internal link (TreeDropdownField) or an external link (TextField). If one is filled out, the other should not display.

The Display Logic module allows you to create a very verbose set of logic that, when evaluated, determines whether the field should show or hide. And it $looks->absolutely(“Beautiful”)->thanksTo(“chainable methods”)!

Best of all, it works with Bootstrap Forms!

Example Usage

$products->displayIf("HasProducts")->isChecked();

$sizes->hideUnless("ProductType")->isEqualTo("t-shirt")
      ->andIf("Price")->isGreaterThan(10);

$payment->hideIf("Price")->isEqualTo(0);

$shipping->displayIf("ProductType")->isEqualTo("furniture")
           ->andIf()
              ->group()
                ->orIf("RushShipping")->isChecked()
                ->orIf("ShippingAddress")->isNotEmpty();
              ->end();

 More Information

Please checkout the Github page for more information, including documentation.

26 Responses to “Display Logic Module for SilverStripe 3”

  1. Simon 28. Jan, 2013 at 4:45 pm #

    Are you using Entwine here to trigger things?
    Also, is there a specific reason for using the Field::create() method?
    I like the new FieldType(); method more, personally. It might not be the best method, but the create-method is cluttery to me.

    • Will 28. Jan, 2013 at 5:55 pm #

      Field::create() hooks into the new Dependency injection framework in 3.0 allowing greater customization of those fields.

      • unclecheese 28. Jan, 2013 at 5:57 pm #

        Yup. What he said. Also it hooks into Object::useCustomClass(), and if you’re in PHP < 5.4, it makes the instantiation chainable.

      • Will 28. Jan, 2013 at 5:58 pm #

        Also nice work Aaron! Liking the fluent api use. So this supports front end forms as well as CMS forms?

        • unclecheese 28. Jan, 2013 at 6:15 pm #

          Thanks, Will. Yes. It’s controller agnostic.

      • Simon 29. Jan, 2013 at 6:18 am #

        Ah, ok, then it definitely makes sense. I’m going to rewrite some of my backend I guess.
        Hadn’t realized/read that.
        I guess cluttery looking functionality over preferred cleanliness :)

  2. Jose A. 29. Jan, 2013 at 4:43 am #

    Aaron, wonderful work! You’re a crack. :)

  3. Matthew Balaam 29. Jan, 2013 at 8:04 am #

    Another very useful module. Thanks!

    I am trying out the following code in conjunction with your Bootstrap Forms module:

    OptionsetField::create(‘Options’,_t(‘Content.Options’, ‘option?’))
    ->setSource(array(‘Option1′, ‘Option2′)),

    EmailField::create(‘Option1′,_t(‘Content.Option1′, ‘Option1′))
    ->displayIf(‘Options’)->isEqualTo(‘Option1′)->end(),

    TextField::create(‘Option2′,_t(‘Content.Option2′, ‘Option2′))
    ->displayIf(‘Options’)->isEqualTo(‘Option2′)->end(),

    This then produces the following code:

    – All my regular scripts then appear here, followed by bootstrap_forms.js, jquery.entwine-dist.js and display_logic.js
    – Then this comes next: ($(“#Options”).evaluateEqualTo(“Option1″))

    ….

    • Matthew Balaam 29. Jan, 2013 at 8:06 am #

      That seems to have stripped my code. Should be:

      [div id="Option1" etc.]
      [label etc.]
      [div class="controls"]
      [input name="Option1" etc.]
      [/div]

      – All my regular scripts then appear here, followed by bootstrap_forms.js, jquery.entwine-dist.js and display_logic.js
      – Then this comes next: [script type="text/template" class="display-logic-eval"]($(“#Options”).evaluateEqualTo(“Option1″))[/script]
      [/div]

      [div id="Option2" etc.]

      ….

      • unclecheese 29. Jan, 2013 at 8:41 am #

        Yeah, that’s a really annoying feature of the Requirements system. If you have Requirements::$write_js_to_body enabled, it looks for the first script tag in the body and appends everything after that, rather than just putting everything before the closing body tag. One fix is to set Requirements::set_write_js_to_body(false);, but not everyone likes to do that.

        In a perfect world, it makes the most sense for the parseable logic string to be in a script tag, because it’s naturally hidden, and it is, well, script. But I suppose we could change that to a div and apply a display none to it with CSS. I’m not crazy about it, but I do see the limitation, and I’d much rather a practical solution than a conceptually perfect one.

        • Matthew Balaam 29. Jan, 2013 at 9:35 am #

          Thanks, it makes sense now, I’ve had these issues with requirements before, I wish it was more flexible.

          • unclecheese 29. Jan, 2013 at 9:50 am #

            Can you try changing the script tag to a div (and removing the type attribute) from all the templates that come with the module and let me know if that works?

            Requirements is a can of worms. There needs to be a much more strict dependency management system in place, but there are many ways to do it, and none of them perfect. One of the biggest flaws I see in Requirements right now (for which I don’t have a fix) is that dependencies are called by path, not by name. It’s easy to end up with three or four different jQuery sources in your document!

  4. Matthew Balaam 29. Jan, 2013 at 10:07 am #

    I‘m not sure if this is exactly what you asked for but I changed to:

    This shows all options. Clicking any of the linked radio buttons then toggles all options.

  5. Matthew Balaam 29. Jan, 2013 at 10:07 am #

    Sorry, forgot about tags. [div class="display-logic-eval"][/div]

    • unclecheese 29. Jan, 2013 at 11:00 am #

      Hi, Matthew,

      You haven’t set the source of your OptionsetField properly. Be sure to pass key/value pairs rather than a list, because as you have it, the value you should be checking for is “0″ or “1″..

  6. Andrew Houle 29. Jan, 2013 at 2:18 pm #

    So much cleaner then the hacked up logic I’ve used in the past. Can’t wait to try this!

  7. Andrew Houle 30. Jan, 2013 at 9:39 am #

    Is there a way to listen for if a has_one image has been added? My first attempt was $photooption->displayIf(“Photo”)->isNotEmpty();

    • unclecheese 01. Feb, 2013 at 2:13 pm #

      No support for upload fields. They don’t fire change events. Maybe we can get Zauberfisch to add one

  8. Lx 02. Feb, 2013 at 7:39 am #

    Wow, that looks really cool.
    The rules remind me of our netefx validator.
    But with this chaining they are much smarter.
    So maybe you can reuse this to build a validator of it.

    Regards
    Lx

  9. guci0 06. Feb, 2013 at 10:14 am #

    Miodzio :)

  10. nicolaas 12. Feb, 2013 at 4:20 am #

    love it.

  11. francisco arenas 17. Feb, 2013 at 7:18 pm #

    do i hear silversmith addon??? :D

  12. CW 04. Mar, 2013 at 2:35 am #

    Can anyone verify that their default “Insert Link” popup works with this module?

    Cos when I installed this, the js that handles the default “Insert Link” popup doesn’t seem to fire and everything just displays.

    Is there a clash somewhere?

    • unclecheese 04. Mar, 2013 at 10:24 am #

      Yeah, I just confirmed it. It’s not a JS issue as far as I can tell. If you delete /display_logic/templates/Includes/FormField_holder.ss it works. (But you lose the display logic features).

      This one’s a bit of a mystery right now.

    • unclecheese 10. Mar, 2013 at 2:49 pm #

      This bug is fixed.

      • CW 10. Mar, 2013 at 10:46 pm #

        Thanks unclecheese!

Leave a Reply