sn-record-picker Helper, Part II

“If I had eight hours to chop down a tree, I’d spend six hours sharpening my ax.”
Abraham Lincoln

Now that we have all of the form fields and controls laid out on the page, the next order of business is to build the function that will use the form input to create the desired sn-record-picker. We have already specified an ng-submit function on the form, so all we have to do at this point is to actually create that function in the client-side script. This function is actually pretty vanilla stuff, and just takes the data entered on the screen and stitches it all together to form the resulting sn-record-picker tag.

$scope.createPicker = function() {
	var picker = '<sn-record-picker\n    table="' + "'";
	picker += c.data.table.value + "'";
	picker += '"\n    field="';
	picker += c.data.field;
	if (c.data.filter) {
		picker += '"\n    default-query="' + "'";
		picker += c.data.filter + "'";
	}
	picker += '"\n    display-field="' + "'";
	picker += c.data.displayField.value + "'";
	if (c.data.displayFields.value) {
		picker += '"\n    display-fields="' + "'";
		picker += c.data.displayFields.value + "'";
	}
	if (c.data.searchFields.value) {
		picker += '"\n    search-fields="' + "'";
		picker += c.data.searchFields.value + "'";
	}
	if (c.data.valueField.value) {
		picker += '"\n    value-field="' + "'";
		picker += c.data.valueField.value + "'";
	}
	if (c.data.multiple) {
		picker += '"\n    multiple="true"';
	}
	if (c.data.placeholder) {
		picker += '"\n    page-size="';
		picker += c.data.pageSize;
	}
	if (c.data.pageSize) {
		picker += '"\n    placeholder="';
		picker += c.data.placeholder;
	}
	c.data.generated = picker + '">\n</sn-record-picker>';
	c.data.ready = true;
	return false;
};

One of the last few things that happens in that script is to set c.data.ready to true. I set that variable up to control whether or not the rendered tag should appear on the screen. Altering any of the fields on the screen sets it to false, which hides the text box containing the generated code until you click on the button again. To make that work, I just added an ng-show to the enclosing DIV:

<div class="col-sm-12" ng-show="c.data.ready">
  <snh-form-field
    snh-model="c.data.generated"
    snh-name="generated"
    snh-label="Your sn-record-picker:"
    snh-type="textarea">
  </snh-form-field>
  <p><a href="javascript:void(0);" onclick="copyToClipboard();">Copy to clipboard</a></p>
</div>

The other thing that you will notice inside of that DIV is the Copy to clipboard link. That one uses a standard onclick rather than an ng-click, because that’s a DOM operation, which is outside the scope of the AngularJS controller. The referenced script, along with another DOM script that I use to set the height of that textarea, are placed in a script tag with the HTML.

<script>
function fixTextareaHeight() {
	var elem = document.getElementById('generated');
    elem.style.height = (elem.scrollHeight + 10)  + 'px';
}
function copyToClipboard() {
	var elem = document.getElementById('generated');
	elem.select();
	elem.setSelectionRange(0, 99999)
	document.execCommand('copy');
	alert("The following code was copied to the clipboard:\n\n" + elem.value);
}
</script>

Clicking on that Copy to clipboard link copies the code to the clipboard and also throws up an alert message to let you know what was copied.

Alert message after copying the code to the clipboard

The next thing on my list was to actually place the code on the page so that you could see it working. I tried a number of things to get that to work, including ng-bind, ng-bind-html, ng-bind-html-compile, and sc-bind-html-compile, but I could never get any of that to work, so I ultimately gave up on trying to use the actual generated code, and did the next best thing, which was to just set up a picker of my own using the selected options.

        <div class="col-sm-12" ng-show="c.data.ready">
          <snh-form-field
            snh-model="c.data.liveExample"
            snh-name="liveExample"
            snh-label="Live Example"
            snh-type="reference"
            snh-change="optionSelected()"
            placeholder="{{c.data.placeholder}}"
            table="c.data.table.value"
            display-field="c.data.displayField.value"
            display-fields="c.data.displayFields.value"
            value-field="c.data.valueField.value"
            search-fields="c.data.searchFields.value"
            default-query="c.data.filter">
          </snh-form-field>
        </div>

This approach allowed me to add a modal pop-up that showed the value of the item selected.

Modal pop-up indicating option selected

The code to make that happen is in the client-side controller:

$scope.optionSelected = function() {
	spModal.open({
		title: 'Selected Option',
		message: '<p>You selected  "<b>' + c.data.liveExample.value + '</b>"</p>',
		buttons: [
			{label: 'Close', primary: true}
		],
		size: 'sm'
	});
};

One other thing that I should mention is that the snh-form-field directive that I used in this example is not same as the last version that I had published. To support the multiple=true/false option, I needed a checkbox, and for some reason, I never included that in the list of many, many field types that included in that directive. I also had to tweak a few other things here and there, so it’s no longer the same. I should really release that separately in a future installment, but for now, I will just bundle it with everything else so that this will all work as intended.

I wrapped the whole thing in an snh-panel, just to provide the means to add some documentation on the sn-record-picker tag. I had visions of gathering up all of the documentation that I could find and assembling it all into a comprehensive help screen document, but that never happened. Still, the possibility is there with the integrated help infrastructure.

Pop-up widget help screen

I also added a sidebar menu item so that I could easily get to it within the main UI. It may be a Service Portal Widget under the hood, but it doesn’t really belong on the Service Portal. It’s a development tool, so I added the menu item so that it could live with all of the other development tools in the primary UI. If you want to take it for a spin yourself, here is an Update Set.

Update: There is a better (corrected) version here.