Search code examples
javascriptformssymfonymaterialize

Symfony best practice - using Materialize CSS Chips with Symfony Forms


I've begun a project in Symfony 3 which needs to allow users to create a post with some data, and a collection of tags (many-to-many). The CSS framework I've been using is MaterializeCSS and there's a handy class called 'chips' which would be nice to allow input for the tags.

I've been using the Form objects as per the Symfony guide with no issues so far, however my issue is that the materialize CSS constructs its 'Chips' field like this:

  <div class="chips"></div>

...

  $('.chips').material_chip();

I can't for the life of me see how to do this inside of a Symfony form, or how to retrieve the data after submission if done with custom form rendering. I could just not use it, but the UX would suffer. I've read a bit about the CollectionType class inside of Symfony but I'm still not sure that this would be appropriate to use with chips.

I'm sure somebody's completed a project like this before, would be great to have some input. All help appreciated.


Solution

  • As we discussed above , the idea is to have some glue js code to manipulate a hidden field which contains tags as comma separated values and bind the chip widget with that hidden field as data source and target e.g

    Desired html

      Input field(might be hidden):
      <input name="chips" value="Apple,Hello,World">
    
      The Chip:
      <div class="chips"/>
    

    Glue js

    <script>
         function updateChipInput(chip){
           var newval= $(chip).material_chip('data')
              .reduce(function(result,val){ result.push(val.tag); return result;},[]).join(",")
    
           $('input[name="chips"]').val(newval);
         }
    
        $(document).ready(function(){
         var data= $('input[name="chips"]').val().split(',') 
           .map(function(tag){
             return {tag:tag}
           })
    
         $('.chips').material_chip({
           data: data          
        });
    
         $('.chips').on('chip.add', function(e, chip){
           updateChipInput(this);
        })
         .on('chip.delete', function(e, chip){
           updateChipInput(this);
        });  
       });
      </script>
    

    working demo

    The input is text field to show the effects in example you can set its type to hidden ,thanks