Binding Dropdown Fields in Semantic UI

I've been trying out Semantic-UI recently and it really appeals to me on a lot of levels.  I thought I'd show a quick example of how to bind one dropdown (Semantic's version of a select form field) to another.  This comes in handy if you're trying to filter the options of one based on the other.

Besides all the semantic dependencies (jQuery, semantic.js, various css etc.) there are four files we'll look at: 

  • index.cfm - the view
  • baseapi.cfc - the ColdFusion component that provides base api functionality (see Ben Nadel's blog for more info on this)
  • art.cfc - the ColdFusion component that returns our data
  • custom.js - the custom javascript that makes the magic happen

Here's our view (index.cfm):




<!DOCTYPE html>



<head>

   <meta charset="utf-8"/>

   <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/>

   <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">

   

   <title>Semantic Drop-Down Field Binding</title>

   

   <link href="semantic/packaged/css/semantic.css" rel="stylesheet" type="text/css">

   <link href="assets/css/style.css" rel="stylesheet" type="text/css">

   

   <script src="http://code.jquery.com/jquery-1.10.2.min.js"></script>

   <script src="semantic/packaged/javascript/semantic.js"></script>

   <script src="assets/javascript/custom.js"></script>

</head>



<body>

   <cfquery datasource="cfartgallery" name="qArtists">

      SELECT ARTISTID, FIRSTNAME, LASTNAME

      FROM ARTISTS

      ORDER BY LASTNAME, FIRSTNAME

   </cfquery>



   <div class="ui blue segment" id="Manager-AddCoupon-View">



      <p>

      <i class="large comment outline icon"></i>This is an example of the second dropdown being binded to the first.

      </p>



      <div class="ui basic form segment">



      <form id="ArtistForm" name="ArtistForm">



      <div class="field">

         <div class="ui segment">

         <div class="ui blue ribbon label">Artists</div>

         <div class="ui dropdown selection" id="ArtistsDD">

            <input type="hidden" name="Artist">

            <div class="default text">Select an artist</div>

            <i class="dropdown icon"></i>

            <div class="menu" id="artistMenu">

               <cfoutput>

                  <cfloop query="#qArtists#">

                     <div class="item" data-value="#ARTISTID#">#FIRSTNAME# #LASTNAME#</div>

                  </cfloop>

               </cfoutput>

            </div>

         </div>

         </div>

      </div>



      <div class="field">

         <div class="ui segment">

         <div class="ui blue ribbon label">Art</div>

         <div class="ui dropdown selection" id="ArtDD">

            <input type="hidden" name="Art">

            <div class="default text">Select art</div>

            <i class="dropdown icon"></i>

            <div class="menu" id="artMenu">

            </div>

         </div>

         </div>

      </div>



      <div class="ui black inverse button" onclick="showPicks();">What did I pick?</div>



      </form>



      </div>



   </div>

</body>



<script>

$(document).ready(function() {

   $('.ui.dropdown').dropdown();

   $('#ArtistsDD')

      .dropdown('setting',{

         onChange : showArt

         }

      )

   ;

});

</script>



The BaseAPI.cfc looks like this:




<cfcomponent output="false" hint="I provide the base API functionality.">



   <cffunction name="GetNewResponse"

               access="public"

               returntype="struct"

               output="false"

               hint="I return a new API response struct.">



      <cfset var LOCAL = {}/>

      <cfset LOCAL.Response = { Success=true, Errors=[], Data="" }/>

      <cfreturn LOCAL.Response/>



   </cffunction>



</cfcomponent>



 

This is Art.cfc:




<cfcomponent   extends="BaseAPI"

               output="false"

               hint="I am the public API for art.">



   <cffunction name="getArtByArtistID"

               access="remote"

               returntype="struct"

               returnformat="json"

               output="false"

               hint="I return the art for a given artist.">



               <cfargument name="ArtistID"

                           type="numeric"

                           required="true"

                           hint="I am the Artist ID" />



               <cfset var LOCAL = {} />

               <cfset LOCAL.Response = THIS.GetNewResponse()/>



               <cfif NOT Len( trim(ARGUMENTS.ArtistID) )>

                  <cfset ArrayAppend( LOCAL.Response.Errors, "Please choose an artist" )/>

               </cfif>



               <cfif NOT ArrayLen( LOCAL.Response.Errors )>

                  <cfset qry = '' />

                  <cfquery datasource="cfartgallery" name="qry">

                  SELECT       ARTID,

                                     ARTNAME

                  FROM         ART

                  WHERE      ARTISTID = <cfqueryparam value="#ARGUMENTS.ArtistID#" cfsqltype="cf_sql_integer" />

                  ORDER BY ARTNAME

                  </cfquery>

                  <cfset LOCAL.Response.Data = qry />

               </cfif>



               <cfif ArrayLen( LOCAL.Response.Errors )>

                  <cfset LOCAL.Response.Success = false/>

               </cfif>



               <cfreturn LOCAL.Response/>



   </cffunction>



</cfcomponent>



and finally the custom.js javascript file:




/*

Filename:      custom.js

Created by:    Kris Korsmo

Organization:  Leading Edge Digital Media - www.leadingedge.net

Purpose:       JavaScript functions for Semantic UI Binding Demo

Last Updated:  12/19/2013

*/



showArt = function(){

   

   var thisArtist = $('#ArtistsDD').dropdown('get value');



   var objSelf = this;

   $.ajax({

      type: "get",

      url: "./api/art.cfc",

      data: {

         method: "getArtByArtistID",

         ArtistID: thisArtist

      },

      dataType: "json",

      success: function(objResponse){

         if (objResponse.SUCCESS) {

            var artData = objResponse.DATA.DATA;

            var numArt = artData.length;

            $('#artMenu .item').remove();

            if(numArt == 0){

               alert('This artist has no art\nPlease select another artist');

            }

            for(i=0;i < numArt;i++){

               var thisArtID = artData[i][0];

               var thisArtName = artData[i][1];

               //console.warn(thisArtist + ' - ' + thisArtName);

               $('#artMenu').append('<div class="item" data-value="' + thisArtID + '">' + thisArtName + '</div>');

               

            }

               $('#ArtDD').dropdown();

               $('#ArtDD').dropdown('set text',"Select art");

         }

         else {

             objSelf.ShowErrors(objResponse.ERRORS);

         }

      },

      error: function(objRequest, strError){

         console.error('qbjRequest: ' + objRequest);

         console.error('strError: ' + strError);

      }

   });

}



showPicks = function(){

   var selectedArtist = $('#ArtistsDD').dropdown('get text');

   var selectedArt = $('#ArtDD').dropdown('get text');

   alert('You selected\nArtist: ' + selectedArtist + '\nArt: ' + selectedArt);

}



Here's the code in action: Example

No comments yet.

(will not be published)
Leave this field empty: