Transforming the Grid Picker

2456

Comments

  • john_doylejohn_doyle Cireson Support Ninja IT Monkey ✭✭✭✭
    Excellent! I will add that snippet into the code.
  • Konstantin_Slavin-BoKonstantin_Slavin-Bo Customer Advanced IT Monkey ✭✭✭
    I agree is a little bit clunky. Sometimes if you select an object and you go back to delete it it will show the 3 green dots seaching again and may take 10-20 seconds before returns your search (in our case is searching about  8500 users) , other times if you type another name it will show you the dropdown with the objects meeting your search criteria, is so random. 
    So I imported 20k users into SCSM and sync'ed that over to the ServiceManagement DB and for me the picker still loads instantly. I don't see the original query picker at all. Searching sometimes takes up to maybe 1-3 seconds, but no more than that.

    Did you switch to use ajaxComplete() instead of ajaxStop()? And made sure, that the .unbind below is also changed to ajaxComplete()?

    What browser are you using?
  • Adrian_MataiszAdrian_Mataisz Customer Advanced IT Monkey ✭✭✭
    Thanks Konstantin. Work fine now, search loads instantly. Thank you all for guidance and sharing the code. Much Appreciated!
  • Konstantin_Slavin-BoKonstantin_Slavin-Bo Customer Advanced IT Monkey ✭✭✭
    Another idea for the toolbox (idea from here): Specify a placeholder on a text prompt. I'm not sure what functionality would be best here; Should the "title" of the prompt to be the placeholder (i.e. the actual title will be removed above the prompt), or should it be possible to define a placeholder different from the title, and the title remains above the prompt?

    It could of course have both functionalities by defining that if the tag includes a string, the title should remain, i.e. @placeholder("this should be the placeholder") or simply @placeholder to use the title as placeholder.
  • Konstantin_Slavin-BoKonstantin_Slavin-Bo Customer Advanced IT Monkey ✭✭✭
    So I implemented a simple @placeholder with this little piece of code:

    function makePlaceholder()
    {
      var that = $(this);
      that.hide();
     
      // Get question div
      var question = that.next();
      var placeholder = question.find('label.control-label').text();
      // Hide title on question
      question.find('label.control-label').hide();
     
      // The text is loosing the space before Required, so we need to insert it
      placeholder = placeholder.replace('(', ' (');

      var textPrompt = question.find('textarea');
      // Add placeholder attribute to textarea
      textPrompt.attr('placeholder', placeholder); 
    }


    If of course needs to be called in the ajaxComplete event as so:
    $("p:contains('@placeholder')").parent().parent().each(makePlaceholder);

    As with the other controls. it looks for a prompt containing "@placeholder", and then takes the next prompts Title and inserts it as placeholder in the text prompt.

    Example with and without placeholder:


    I would like to implement the functionality as I described in my last post, allowing one to input @placeholder(something), such that that text would become the placeholder, but I'm not sure, how I would distinguish between a tag with and without text (do you have an idea @john_doyle?).

    Ideally, this tag could even be in the title for the specific prompt itself (so not another prompt), but I'm still considering how that could/should be done.



  • Konstantin_Slavin-BoKonstantin_Slavin-Bo Customer Advanced IT Monkey ✭✭✭
    allowing one to input @placeholder(something),
    I guess it could be done by removing "@placeholder(" and ")" from that.text() and then using that value, but aren't there a better way?
  • john_doylejohn_doyle Cireson Support Ninja IT Monkey ✭✭✭✭
    edited June 2017
    Hi @Konstantin_Slavin-Bo thanks for the code. I'll add that into the toolbox.

    I have been working a little more on the code myself and adding a mechanism for adding properties to the tags, so for example, I want to be able to let the admin define the minLength on the autocomplete control. I do this by adding a JSON object to the tag, like this:

    @AutoComplete {"minLength": "3"}

    (Note that I decided to change the tag names going forward. Hopefully this will not cause too much distress, but it is easy to change them back in the js file anyway)

    Anyway, the code still searches for the tag like this:
        if ( !($( "div.custom-item-picker" ).length) ) {
            $("p:contains('@AutoComplete')").parent().parent().each(function() {createAutoComplete("@AutoComplete",$(this))});

    the createAutoComplete function now takes two arguments:

    function createAutoComplete(tag,tagElement)
    {
        var userDefined = parseOptions(tag,tagElement);
        // Hide the out of the box controls
        tagElement.hide();

    the parseOptions function is like this:

    function parseOptions(controlName,control) {
        var properties = "{}";
        var regExp = /({[^}]+})/;
        var matches = regExp.exec(control.text());
        if (matches[1]) properties = matches[1];
        return JSON.parse(properties);
    }

    I can then reference the properties set in the JSON string as userDefined.minLength (for example). I do need to do some more work on the tools before posting a new version.



  • Eric_KrasnerEric_Krasner Customer Advanced IT Monkey ✭✭✭
    @john_doyle are you going to post an updated download file?  It's a lot of changes to keep track of.  Thanks.

  • Konstantin_Slavin-BoKonstantin_Slavin-Bo Customer Advanced IT Monkey ✭✭✭
    Another idea for the toolbox: @confirmField (or something), which ensures that the data entered in the next to text prompts are identical, and show an error / does not let you continue if it doesn't.
  • john_doylejohn_doyle Cireson Support Ninja IT Monkey ✭✭✭✭
    @Eric_Krasner @Konstantin_Slavin-Bo I am attaching the current iteration of the toolbox. A number of things have changed. @Konstantin_Slavin-Bo I added your placeholder control. I also added a date range control, and a control which allows you to add a class definition to the next control on the form.

    I changed the names of the original tags, so if you have implemented the previous version, you will need to either change the tags on your forms or edit the function which searches for the tags.

  • Konstantin_Slavin-BoKonstantin_Slavin-Bo Customer Advanced IT Monkey ✭✭✭
    @john_doyle
    Very nice, the toolbox is starting to take form! Thank you for crediting me, although if you continue to do it, could you please use my full name: Konstantin Slavin-Borovskij? The Cireson username is capped at 20 chars. Thanks!

    I've edited the makePlaceholder function a bit, as you added the replace linebreak with nothing (line 105); I inserted a space in the replace string, and removed the line replacing "(" with " (", i.e.
    placeholder = question.find('label.control-label').text().replace(/\n/g, ' ');

    Also, I've implemented the @ConfirmField I mentioned with a small function:
    function confirmFields(tagElement) {
      tagElement.hide();

      var referencePrompt = tagElement.next().find('textarea');
      var controlPrompt = tagElement.next().next().find('textarea');

      referencePrompt.blur(function() {
        var validationValue = referencePrompt.val();
        controlPrompt.attr("data-validate-value", validationValue);
      });
    }
    It reuses the regex field on the second prompt, to make sure that the two fields match. So the 2nd prompt / "confirm prompt" needs to be to configured to use .Net Regular Expressions with any Regular Expression (e.g. .*) and a Custom ToolTip, which will be shown on mismatch.

    I don't use the tag argument, but I kept tagElement to try and maintain some consistency, so the function call looks like:
    $("p:contains('@ConfirmField')").parent().parent().each(function () {
      confirmFields($(this));
    });

    The @ConfirmFIelds tag should be placed right above the first prompt.
  • Eric_KrasnerEric_Krasner Customer Advanced IT Monkey ✭✭✭
    edited June 2017
    I must be doing something wrong as I cannot get this to work.  I have added the files, no issue.  I have added the prompts and configured the query results.  The RO opens to the new field and all looks good, except no query no matter what or how much I type.  It is just an AD User query.  What am I doing wrong?






  • john_doylejohn_doyle Cireson Support Ninja IT Monkey ✭✭✭✭
    @Eric_Krasner You are searching for users who live in a city called eric?
  • Eric_KrasnerEric_Krasner Customer Advanced IT Monkey ✭✭✭
    Duh, never mind.  Its been a long day
  • Eric_KrasnerEric_Krasner Customer Advanced IT Monkey ✭✭✭
    I would like to report that the form does not consistently come up with the new field.  It does seem hit or miss. Since we are still in the test environment, not a big issue.  But no way could I move to prod till this gets figured out.

    btw, I get the same issue whether I'm using IE or Chrome
  • john_doylejohn_doyle Cireson Support Ninja IT Monkey ✭✭✭✭
    @Eric_Krasner My guess is that the first ajax complete event in your environment is occurring before the form has finished loading in that case. You could try changing back to ajaxStop.
    $(document).ajaxStop(function() {
        $(this).unbind('ajaxStop');

    This may lead to a long delay before the toolbox kicks in.

    Can you try replacing those two lines with this:
    $(window).load( function() {


  • Eric_KrasnerEric_Krasner Customer Advanced IT Monkey ✭✭✭
    That worked
  • Konstantin_Slavin-BoKonstantin_Slavin-Bo Customer Advanced IT Monkey ✭✭✭
    That worked
    Which worked? Changing to ajaxStop or to (window).load?
  • Eric_KrasnerEric_Krasner Customer Advanced IT Monkey ✭✭✭
    Sorry about that.  They both worked.  I chose to go with changing the ajax. It looked the most seamless when the form opened
  • Geoff_RossGeoff_Ross Cireson Consultant Super IT Monkey ✭✭✭✭✭
    @john_doyle. You sir, are amazing.
  • Konstantin_Slavin-BoKonstantin_Slavin-Bo Customer Advanced IT Monkey ✭✭✭
    Okay, so I released the autocomplete in to the wild (to a closed group of analysts on a internal RO we have) and soon got reports that the fields are not consistently being replaced with the new. I've tried both ajaxComplete() and ajaxStop(), and both yield this behavior. I think I didn't catch this myself, because I run my browser with devtools open when working on stuff, so the load times are longer.

    I ended up using (window).load() instead; it can result in a short glimpse of the original fields, but now they are consistently changing to the new one, which is fine for us. It's still a lot better than the crappy OotB fields!
  • john_doylejohn_doyle Cireson Support Ninja IT Monkey ✭✭✭✭
    @Konstantin_Slavin-Bo I think I have found an even better solution. I checked the JavaScript code which the Request Offering page runs as it loads, and found that it publishes an event onto a messaging bus. By subscribing to this event, we can load as the page is rendering.
    Can you test this? Replace the window.load()...etc. with this:

    app.events.subscribe('drawerCreated',transformRO);

     function transformRO() {   
         app.events.unsubscribe('drawerCreated',transformRO);
         app.lib.mask.apply();
        $("p:contains('@Placeholder')").parent().parent().each(function() {
            makePlaceholder("@Placeholder", $(this))
        });
        if (!($("div.custom-item-picker").length)) {
            $("p:contains('@AutoComplete')").parent().parent().each(function() {
                createAutoComplete("@AutoComplete", $(this))
            });
        }
        if (!($("div.custom-item-multipicker").length)) {
            $("p:contains('@MultiSelect')").parent().parent().each(function() {
                createMultiSelect("@MultiSelect", $(this))
            });
        }
        if (!($("div.custom-item-daterange").length)) {
            $("p:contains('@DateRange')").parent().parent().each(function() {
                createDateRange("@DateRange", $(this))
            });
        }
        $("p:contains('@AddClass')").parent().parent().each(function() {
            addCssClass("@AddClass", $(this))
        });
        app.lib.mask.remove();
    }

  • Jeff_LangJeff_Lang Customer Advanced IT Monkey ✭✭✭

    when setting up conditions to only show the grid views on certain conditions, eg a checkbox ticked, this doesn't translate over to the replacement field.



    i have got around this by adding the following at the bottom of the variables at line 207
    var ngshow = targetEle.parent().parent().parent().parent().parent().attr("ng-show");
     then down around line 251 i have replaced
          queryResults.after("<div class='row custom-item-picker' 
    style='margin-bottom:15px;'><div class='col-md-6 col-xs-12'>" +
     controlLabel + "<input id='ac" + targetId + "' style='width: 100%;' 
    /></div></div>");
    with the following

        if ( ngshow != "undefined") {
          queryResults.after("<div class='row custom-item-picker ng-hide' ng-show='" + ngshow + "' onhide style='margin-bottom:15px;'><div class='col-md-6 col-xs-12'>" + controlLabel + "<input id='ac" + targetId + "' style='width: 100%;' /></div></div>");
        } else {
          queryResults.after("<div class='row custom-item-picker' style='margin-bottom:15px;'><div class='col-md-6 col-xs-12'>" + controlLabel + "<input id='ac" + targetId + "' style='width: 100%;' /></div></div>");
        }


    with these changed the custom field gets the same show/hide conditions as the grid, allowing the fields to be hidden or shown as the ones they replace are set to

  • Jeff_LangJeff_Lang Customer Advanced IT Monkey ✭✭✭
    for the same effect on the multi select, adding the same lines at around line 348 (at the bottom of the var list)
    var ngshow = targetEle.parent().parent().parent().parent().parent().attr("ng-show");
    and around line 308 replacing
        queryResults.after("<div class='row custom-item-multipicker' style='margin-bottom:15px;'><div class='col-md-6 col-xs-12'>" + controlLabel + "<select id='ms" + targetId + "' style='width: 100%;' /></div></div>");
    with
        if ( ngshow != "undefined") {
    queryResults.after("<div class='row custom-item-multipicker ng-hide' ng-show='" + ngshow + "' onhide style='margin-bottom:15px;'><div class='col-md-6 col-xs-12'>" + controlLabel + "<select id='ms" + targetId + "' style='width: 100%;' /></div></div>");
    } else {
    queryResults.after("<div class='row custom-item-multipicker' style='margin-bottom:15px;'><div class='col-md-6 col-xs-12'>" + controlLabel + "<select id='ms" + targetId + "' style='width: 100%;' /></div></div>");
    }

    will have it keep the show/hide criteria for it's actual grid view as well








  • Jeff_LangJeff_Lang Customer Advanced IT Monkey ✭✭✭
    @john_doyle & @Konstantin_Slavin-Bo

    I found that when loading the page initially on IE the page loaded with the transformations, but if F5 was pressed to reload it they would not happen and the grid pickers would show.

    i put in the change you had above @john_doyle ; for the "app.events.subscribe('drawerCreated',transformRO);"
    and after replacing the ajax.complete, i found the page did load a LOT faster in IE, and also the grids have not shown up since on over 20 page refresh's, it has only shown the transformed fields as it should.
  • john_doylejohn_doyle Cireson Support Ninja IT Monkey ✭✭✭✭
    @Jeff_Lang I totally forgot the show/hide option. Great work on coding it.
  • Konstantin_Slavin-BoKonstantin_Slavin-Bo Customer Advanced IT Monkey ✭✭✭
    @john_doyle
    Ah, that is excellent! And that event is always fires after the RO is loaded? Either way it passes my stress tests, and it seems to work really well. I encountered a strange thing though: The function call in the event subscriptions needs to include the parentheses and in the unsubscription they needs to be excluded, i.e.:
    app.events.subscribe('drawerCreated', transformRO());

    function transformRO() {
        app.events.unsubscribe('drawerCreated', transformRO);
    If the parentheses are omitted in the subscribe function, the function is never called. If the parentheses are included in the unsubscribe function, the code just silently fails at that line and never continues. Weird, but it works like that for me.

    @Jeff_Lang
    That's a real good catch, it hadn't crossed my mind at all! Your code works great, you just need to compare values with undefined by comparing to typeof the val, i.e:
    typeof ngshow != 'undefined'
    Thanks for sharing!
  • Adrian_PaechAdrian_Paech Customer Advanced IT Monkey ✭✭✭

    Hi All,

    Any chance that a final version of the code can be uploaded with all of these posted amendments?

    Cheers,

    Adrian

  • Jeff_LangJeff_Lang Customer Advanced IT Monkey ✭✭✭
    I've played a bit more with the show/hide criteria, and made some changes that allow up to 3 criteria to be set for the @autocomplete and @multiselect options

    instead of the
    var ngshow = targetEle.parent().parent().parent().parent().parent().attr("ng-show");
    as stated above for both, i now have
    	var ngshow1 = targetEle.parent().parent().parent().parent().parent().attr("ng-show");
    var ngshow2 = targetEle.parent().parent().parent().parent().parent().prev().attr("ng-show");
    var ngshow3 = targetEle.parent().parent().parent().parent().parent().prev().prev().attr("ng-show");

    for both the @AutoComplete Section and @MultiSelect section
    and the @autocomplete section i have changed
        if ( ngshow != "undefined") {
    queryResults.after("<div class='row custom-item-picker ng-hide' ng-show='" + ngshow + "' onhide style='margin-bottom:15px;'><div class='col-md-6 col-xs-12'>" + controlLabel + "<input id='ac" + targetId + "' style='width: 100%;' /></div></div>");
    } else {
    queryResults.after("<div class='row custom-item-picker' style='margin-bottom:15px;'><div class='col-md-6 col-xs-12'>" + controlLabel + "<input id='ac" + targetId + "' style='width: 100%;' /></div></div>");
    }

    to
    	var ngshowprehtml = "<div class='row custom-item-picker' style='margin-bottom:15px;'><div class='col-md-12 col-xs-12'>";
    var ngshowsufhtml = "</div></div>";
    if ( typeof ngshow1 != 'undefined' ) {
    ngshowprehtml = ngshowprehtml + "<div class='row custom-item-picker ng-hide' ng-show='" + ngshow1 + "' onhide style='margin-bottom:15px;'><div class='col-md-12 col-xs-12'>";
    ngshowsufhtml = ngshowsufhtml + "</div></div>";
    }
    if ( typeof ngshow2 != 'undefined' ) {
    ngshowprehtml = ngshowprehtml + "<div class='row custom-item-picker ng-hide' ng-show='" + ngshow2 + "' onhide style='margin-bottom:15px;'><div class='col-md-12 col-xs-12'>";
    ngshowsufhtml = ngshowsufhtml + "</div></div>";
    }
    if ( typeof ngshow3 != 'undefined' ) {
    ngshowprehtml = ngshowprehtml + "<div class='row custom-item-picker ng-hide' ng-show='" + ngshow3 + "' onhide style='margin-bottom:15px;'><div class='col-md-12 col-xs-12'>";
    ngshowsufhtml = ngshowsufhtml + "</div></div>";
    }
    queryResults.after( ngshowprehtml + controlLabel + "<input id='ac" + targetId + "' style='width: 100%;' />" + ngshowsufhtml);

    and in the @MultiSelect section i have changed
        if ( ngshow != "undefined") {
    queryResults.after("<div class='row custom-item-multipicker ng-hide' ng-show='" + ngshow + "' onhide style='margin-bottom:15px;'><div class='col-md-6 col-xs-12'>" + controlLabel + "<select id='ms" + targetId + "' style='width: 100%;' /></div></div>");
    } else {
    queryResults.after("<div class='row custom-item-multipicker' style='margin-bottom:15px;'><div class='col-md-6 col-xs-12'>" + controlLabel + "<select id='ms" + targetId + "' style='width: 100%;' /></div></div>");
    }
    to
    	var ngshowprehtml = "<div class='row custom-item-picker' style='margin-bottom:15px;'><div class='col-md-12 col-xs-12'>";
    var ngshowsufhtml = "</div></div>";
    if ( typeof ngshow1 != 'undefined' ) {
    ngshowprehtml = ngshowprehtml + "<div class='row custom-item-picker ng-hide' ng-show='" + ngshow1 + "' onhide style='margin-bottom:15px;'><div class='col-md-12 col-xs-12'>";
    ngshowsufhtml = ngshowsufhtml + "</div></div>";
    }
    if ( typeof ngshow2 != 'undefined' ) {
    ngshowprehtml = ngshowprehtml + "<div class='row custom-item-picker ng-hide' ng-show='" + ngshow2 + "' onhide style='margin-bottom:15px;'><div class='col-md-12 col-xs-12'>";
    ngshowsufhtml = ngshowsufhtml + "</div></div>";
    }
    if ( typeof ngshow3 != 'undefined' ) {
    ngshowprehtml = ngshowprehtml + "<div class='row custom-item-picker ng-hide' ng-show='" + ngshow3 + "' onhide style='margin-bottom:15px;'><div class='col-md-12 col-xs-12'>";
    ngshowsufhtml = ngshowsufhtml + "</div></div>";
    }
    queryResults.after( ngshowprehtml + controlLabel + "<select id='ms" + targetId + "' style='width: 50%;' />" + ngshowsufhtml);

    with these changes, all 3 items, as in the @AutoComplete/@MultiSelect Display Only Prompts, AND the Optional Text field, AND the Query results prompts, can all have different Show/Hide Criteria.

    This allows up to 3 show/hide criteria to be used to show/hide the transformed control.

  • Jeff_LangJeff_Lang Customer Advanced IT Monkey ✭✭✭
    heh i should have waited to post the above, as i've been working on a SR that requires multiple criteria to show a field, but there are multiple answers that the field needs to show for.

    so I've coded for an extra option that should be placed after the @AutoComplete or @MultiSelect in the ARO, which will allow using the same 3 criteria as above, but either as a "AND" between them or an "OR" between them. By default it will use "AND" for the Criteria, but this can be changed to an "OR" by adding a display only field called "@ShowHideOR" just after the @AutoComplete or @MultiSelect.

    for this to work the following needs to be added/changed.

    Add 2 extra Procedures.
    // add additional attribute "ngshowhide" to input for query results prompt
    // when set this changes the default action for combining multiple
    // Show/Hide Criteria from "AND" to "OR"
    function makeShowHideOR(tag, tagElement) {
    tagElement.hide();
    var userInput = tagElement.next();
    var queryResults = userInput.next();
    var targetEle = queryResults.find('div[data-control="checkboxGridByCriteriaOld"]');
    $(targetEle).attr("ngshowhide", "or");
    tagElement.remove();
    }

    // combine Show/Hide criteria for @AutoComplete and @MultiSelect Controls
    function createngshow(ngshow, ngshowcriteria, ngshowhide) {
    if (ngshow =="") { return ngshowcriteria }
    ngshow = ngshow + ngshowhide + ngshowcriteria;
    return ngshow;
    }
    in the transformRO procedure add the following ABOVE the @autocomplete check
        $("p:contains('@ShowHideOR')").parent().parent().each(function() {
    makeShowHideOR("@ShowHideOR", $(this))
    });
    Replace the ngshow1,2,3 variables in both the @AutoComplete and @MultiSelect with
    	// set vars for preset Show/Hide Criteria
    var ngshowhide = targetEle.attr("ngshowhide");
    var ngshow1 = targetEle.parent().parent().parent().parent().parent().attr("ng-show");
    var ngshow2 = targetEle.parent().parent().parent().parent().parent().prev().attr("ng-show");
    var ngshow3 = targetEle.parent().parent().parent().parent().parent().prev().prev().attr("ng-show");
    In the @AutoComplete procedure, replace everything between
        // Add the HTML template for the AutoComplete control.
    and
       // Process the data returned from the server and may the display columns into one string.
    with
    	// set either "AND" or "OR" for multiple Show/Hide Criteria
    if (ngshowhide == "or") {
    ngshowhide = "||";
    } else {
    ngshowhide = "&&";
    }
    // combine preset Show/Hide Criteria
    var ngshow = "";
    if (typeof ngshow1 != 'undefined') { ngshow = createngshow(ngshow, ngshow1, ngshowhide) }
    if (typeof ngshow2 != 'undefined') { ngshow = createngshow(ngshow, ngshow2, ngshowhide) }
    if (typeof ngshow3 != 'undefined') { ngshow = createngshow(ngshow, ngshow3, ngshowhide) }
    // Add the HTML template for the AutoComplete control, along with Combined Show/Hide Criteria if set
    if (ngshow.indexOf("&&") != -1 || ngshow.indexOf("||") != -1) {
    ngshow = "(" + ngshow + ")";
    queryResults.after("<div class='row custom-item-picker ng-hide' ng-show='" + ngshow + "' onhide style='margin-bottom:15px;'><div class='col-md-6 col-xs-12'>" + controlLabel + "<input id='ac" + targetId + "' style='width: 100%;' /></div></div>");
    } else {
    queryResults.after("<div class='row custom-item-picker' style='margin-bottom:15px;'><div class='col-md-6 col-xs-12'>" + controlLabel + "<input id='ac" + targetId + "' style='width: 100%;' /></div></div>");
    }

    // Process the data returned from the server and may the display columns into one string.
    In the @MultiSelect procedure, replace everything between
        // Add the HTML template for the AutoComplete control.
    and
       // Process the data returned from the server and may the display columns into one string.
    with
    	// set either "AND" or "OR" for multiple Show/Hide Criteria
    if (ngshowhide == "or") {
    ngshowhide = "||";
    } else {
    ngshowhide = "&&";
    }
    // combine preset Show/Hide Criteria
    var ngshow = "";
    if (typeof ngshow1 != 'undefined') { ngshow = createngshow(ngshow, ngshow1, ngshowhide) }
    if (typeof ngshow2 != 'undefined') { ngshow = createngshow(ngshow, ngshow2, ngshowhide) }
    if (typeof ngshow3 != 'undefined') { ngshow = createngshow(ngshow, ngshow3, ngshowhide) }
    // Add the HTML template for the @MultiSelect control, along with Combined Show/Hide Criteria if set
    if (ngshow.indexOf("&&") != -1 || ngshow.indexOf("||") != -1) {
    ngshow = "(" + ngshow + ")";
    queryResults.after("<div class='row custom-item-multipicker ng-hide' ng-show='" + ngshow + "' onhide style='margin-bottom:15px;'><div class='col-md-6 col-xs-12'>" + controlLabel + "<select id='ms" + targetId + "' style='width: 100%;' /></div></div>");
    } else {
    queryResults.after("<div class='row custom-item-multipicker' style='margin-bottom:15px;'><div class='col-md-6 col-xs-12'>" + controlLabel + "<select id='ms" + targetId + "' style='width: 100%;' /></div></div>");
    }

    // Process the data returned from the server and map the display columns into one string.
    Now we have the option for up to 3 sets of criteria, using a "AND" as default, and if setting the @ShowHideOR then it will use "OR" instead.
Sign In or Register to comment.