Simple custom javascript example returning errors

Hi,

I'm attempting to implement a basic typeahead example (using https://twitter.github.io/typeahead.js/examples/) as proof of concept in Plumsail. I have used this method successfully in customizing out of the box SharePoint forms. Our environment is SharePoint 2019 on-premise.

My complete javascript code is:
window.$ = $;
window.define = null;

fd.spRendered(function() {

  $.getScript("{Web URL}/JQuery/typeahead/typeahead.bundle.min.js")
  .then(function() {
	
    var states = ['Alabama', 'Alaska', 'Arizona', 'Arkansas', 'California',
   'Colorado', 'Connecticut', 'Delaware'
    ]; //Trimmed for brevity
	
	fd.field('Title').value = "Alabama"; //This works
	
	$(fd.field('Title')).typeahead({
      highlight: true,
    },
    {
      name: 'states',
      local: states
    })
	
  })
	
});

I am getting multiple errors in the console having tried a variety of approaches. The ones I believe specific to this are:

VM2330 spform.js:44 TypeError: Cannot read property 'openDialogFuncName' of undefined

VM2384:7 Uncaught ReferenceError: jQuery is not defined

VM2330 spform.js:73 jQuery.Deferred exception: $(...).typeahead is not a function TypeError: $(...).typeahead is not a function

Any ideas?
Thanks

Hello @Andrew,

Are you considering a paid support option?

With paid support, we can help with the code. If you are interested, please contact us via support@plumsail.com for more details.

Hi @mnikitina

Yes I have standard support plan having recently purchased forms, perhaps I've asked too much for a single forum question.

However, after reformatting my code and implementing the requirejs method from your post here: Load external script files via HTML control I have now reduced the issue to a single error after the script is being included:

$(...).typeahead is not a function

I have referenced the same external script in a vanilla aspx page on the same SharePoint environment and it is working so I know it's not an issue with the external js file.

Would you still recommend sending a support request?

Thanks,
Andrew

Hello @Andrew,

The below code works for me. Note that you need to assign a CSS class to the Title field, e.g. typeahead.
image

window.$ = $;
window.jQuery = jQuery;
 
fd.spRendered(function() {   

    // To avoid conflicts with requireJS which is available by default in SharePoint
    // we unset 'define' function until the script are loaded 
    var define = window.define;
    window.define = undefined;
    
    $.getScript('https://cdnjs.cloudflare.com/ajax/libs/corejs-typeahead/1.3.1/typeahead.bundle.min.js')
    .then(function() {
    
        window.define = define;
    
        var substringMatcher = function(strs) {
        return function findMatches(q, cb) {
            var matches, substringRegex;

            // an array that will be populated with substring matches
            matches = [];

            // regex used to determine if a string contains the substring `q`
            substrRegex = new RegExp(q, 'i');

            // iterate through the pool of strings and for any string that
            // contains the substring `q`, add it to the `matches` array
            $.each(strs, function(i, str) {
              if (substrRegex.test(str)) {
                matches.push(str);
              }
            });

            cb(matches);
          };
        };
     
	    var states = ['Alabama', 'Alaska', 'Arizona', 'Arkansas', 'California', 'Colorado', 'Connecticut', 'Delaware']; 
	
	    $('.typeahead input.form-control').typeahead({
            hint: true,
            highlight: true,
            minLength: 1
        },
        {
            name: 'states',
            source: substringMatcher(states)
        });
    });
});

Thanks @mnikitina it was how to handle the define function correctly that was causing me the issue. I have it working now, calling a remote api for the typeahead and then auto populating other fields based on the selection, great functionality to include on my Plumsail forms!

Have to say, although new to Plumsail, as a developer for SharePoint the Plumsail forms are definitely the best form product I've used on the platform. Good support too!

1 Like

I have attempted to do the same as the above with a text field, using typeahead to show some filtered results from a list using PnP-JS.

The idea is that that list is filtered based on some lookup values in my form matching the lookup values in the list, this all works fine but I've noticed when clicking or using tab to select the TypeAhead option, the form only shows the text typed by the user.

For example, Tree Top Hill appears as a search result but when I type Tree in the field and select the typeahead option, only 'Tree' ends up being saved in the field.

Can you see what I'm doing wrong to cause this bug?

  $.getScript('https://cdnjs.cloudflare.com/ajax/libs/corejs-typeahead/1.3.1/typeahead.bundle.min.js')
        .then(function() {
        
            window.define = define;
        
            var substringMatcher = function(strs) {
            return function findMatches(q, cb) {
                var matches, substringRegex;

                // an array that will be populated with substring matches
                matches = [];

                // regex used to determine if a string contains the substring `q`
                substrRegex = new RegExp(q, 'i');

                // iterate through the pool of strings and for any string that
                // contains the substring `q`, add it to the `matches` array
                $.each(strs, function(i, str) {
                  if (substrRegex.test(str)) {
                    matches.push(str);
                  }
                });

                cb(matches);
              };
            };  

			//destroy any previous typeahead formatting on this form
			$('.typeahead').typeahead('destroy');
			
			function populateNewAccommodations (){
				var locations = [];
				var countryFilter = fd.field('CountryLookup').value.LookupId;
                console.log(countryFilter);
				var cityFilter = fd.field('CityLookup').value.LookupId;
                console.log(cityFilter);
				
				if (countryFilter > 0 && cityFilter > 0) {
				
					sp.web.lists.getByTitle('Itinerary').items.select("CountryLookupId","CityLookupId","Accommodation").filter('CountryLookupId eq ' + countryFilter + ' and CityLookupId eq ' + cityFilter).get().then(function(results){
						results.forEach(function(result){
							locations.push(result.Accommodation);
						});
					}).then(function(){
					
						$('.typeahead input.form-control').typeahead({
							hint: true,
							highlight: true,
							minLength: 3
						},
						{
							name: 'locations',
							source: substringMatcher(locations)
						});
					
					
					});
				}
			}
		
			fd.field('CountryLookup').$on('change',function(){
				populateNewAccommodations();			
			});
    	
    	    fd.field('CityLookup').$on('change',function(){
				populateNewAccommodations();			
			});
        });

Hello @abolam,

What do you mean with 'using tab to select the TypeAhead option'? Do you mean that you click on tab key to select the specific value?

Could you please provide more details, maybe some screenshots, so I could have a full picture.
Thank you!

Hi @abolam,

I found this behaviour as well, what I did was to use the bind event to force the selection to be set as the value for the text field.

So in your example it'd be something like:

$('.typeahead input.form-control').typeahead({
	hint: true,
	highlight: true,
	minLength: 3
},
{
	name: 'locations',
	source: substringMatcher(locations)
}).bind('typeahead:select', function(ev, data) {
    fd.field('CountryLookup').value = data.Accomodation
});

You might have to console log that data parameter to make sure the dot value is correct

1 Like

Thanks @Andrew! Will give that a try!