Visually hidden field with ‘required’ attribute causes error: “An invalid form control with name=’xxxxx’ is not focusable.”

Situation

Receive a JavaScript console error of An invalid form control with name='xxxxx' is not focusable when trying to submit the form.

I asked one of my developers to comment out a field in a web page as part of a requirements change (I prefer to comment out initially before deleting so we are sure everything works fine with the change).

The developer added a style="display: none" to a surrounding div to hide a <select> field.

However, this in turn caused a JavaScript console error of An invalid form control with name='xxxxx' is not focusable when trying to submit the form.

 

Solution

Remove the “required” attribute from the form element.

In helping my developer I did a Google search for “an invalid form control with name=” is not focusable” and one of the first results lead to https://stackoverflow.com/questions/22148080/an-invalid-form-control-with-name-is-not-focusable.

On that page I immediately saw “Adding a novalidate attribute to the form will help” and that made me to immediately remember there is a “required” attribute still on the field that was hidden.

Experience and instinct kicked in.

We removed the “required” attribute and the form submission worked.

My guess is when the form was submitted the native browser-based validation did not work correctly because the specified field is “visually” hidden so the native validation message could not be shown, and that triggered the error in the console.

RegEx: Find occurrences in code, except when commented

Background

I’ve created a debug helper function in my PHP/WordPress development called TraceIt($value, $type, $param1).
TraceIt does a bit more than just echo out a value. It will format echo out based on value type or specified type, can be environmentally switched to not echo, and can write to a log file.

It’s also easier to find where actual tracing is being used versus the legitimate echo output.

The problem is, sometimes I forget to comment a trace, which is no good, especially when trying to perform a redirect.
And while I usually include a string value in the output that I can search for, sometimes in the heat of the debugging moment I forget that.

 

Solution

The easiest [and some may argue “painful”] way to find occurrences of forgotten TraceIt calls is regex.

What I needed was a way to find all instances of “TraceIt” but not “//TraceIt” (already commented).

And here it is:

^(?!([ \t]*\/\/[ \t]*TraceIt)|[ \t]*\/\/).*((^TraceIt)|( TraceIt)|(\tTraceIt)|(;TraceIt))

You can see it in action, with an explanation of each component, at https://regexr.com/46nbq.

The only problem with this is it also picks up instances of TraceIt on a line that already has //TraceIt earlier in the line.  But I can live with those rare occurences for now.

Oh, and don’t forget to use the /gim flags (global, case insensitive and multi-line).

 

The regex will find occurrences like this:

coding is here; TraceIt("aaaa");
TraceIt("aaaa");
another line of code;
TraceIt('bbb'); more code
TraceIt('ccc');
TraceIt('bbb');
some more code; TraceIt("adsfadfa");

But not like this:

//TraceIt("aaaa");
//TraceIt("bbb"); TraceIt("ccc")
// TraceIt("ddd");
// TraceIt("ddd");
// TraceIt("eee");

another line of code;

some code; //TraceIt('fff');
    //     // TraceIt("gggg");

platform_browser_dynamic_1.platformBrowserDynamic is not a function

I received the following error today in a project I’m working on (the relevant part is in bold):

MainModule.bundle.js:27136 Uncaught TypeError: platform_browser_dynamic_1.platformBrowserDynamic is not a function
   at Object.__decorate (MainModule.bundle.js:27136)
   at __webpack_require__ (Polyfills.bundle.js:55)
   at webpackJsonpCallback (Polyfills.bundle.js:26)
   at MainModule.bundle.js:1

You can see my response to a similar problem at https://github.com/angular/angular/issues/10732#issuecomment-417173741.

And my response here as well, for completeness:

I just had the same issue in a project I’m working on. We’re using Angular 5.0.2 and Webpack on Windows in an IIS/ASP.NET project, with our primary browser as Chrome.
My issue randomly appeared after rebooting my PC and loading up my dev environment again (no code or configuration changes).
I managed to resolve the issue after a couple of attempts at starting the project (in Visual Studio) by also browsing to the the app URL Microsoft Edge. It loaded find. I then did a hard refresh (Ctrl+F5) in Chrome and it came good too.
Note: we manually start and leave running Webpack in separate command window, but start the actual application from withing Visual Studio.
My guess is Webpack crapped out behind the scenes and needed some time and a hard refresh in the browser to get the correctly compiled code to the browser again.

Saving yourself with Git (Pro Tip!)

I don’t fully trust source control systems. Not even Git. That’s because I’m an old fella in the industry and I’ve been bitten too many times to fully trust systems.

Point in hand. I just had a merge from ‘develop’ royally screw up some code in such a way the effort to find and fix the change is greater than the effort to just blow away my working branch and pull again from remote.

Pro Tip!

When merging from another branch like ‘develop’ into your working branch, first commit and push your changes to remote.
That way, when your merge screws something up without you realising until after you’ve re-compiled and tested the merge – you do re-compile and test your merges right? – you can reset or blow away the branch (even delete your local branch and pull again if need be) without losing your hard-won changes.

JavaScript helper: getMaxLengthString [TypeScript]

Here’s a quick JavaScript helper snippet to return a trimmed string based on the calculated maximum length of a string to fit the width of a parent container element.

Written in TypeScript.

/**
 * Takes a full string and returns a trimmed version to fit within a parent space.
 * @param fullLengthString  The full length string to trim to a parent space.
 * @param font              String representing the font styling of the text (required to calculate text length).
 * @param maxLengthPixels   Max pixel width of the parent space to fit the text into.
 * @param removeExtraChars  The number of extr characters to remove from the trimmed space, if required. (Default: 0)
 */
private getMaxLengthString(fullLengthString: string, font: string, maxLengthPixels: number, removeExtraChars: number = 0): string {
	let maxLengthString: string = "";

	let canvas = document.createElement("canvas");
	let context = canvas.getContext("2d");
	context.font = font;

	for (let i = 0; i < fullLengthString.length; i++) { // Build the string maxLengthString = maxLengthString + fullLengthString.charAt(i); // Test the length of the string let metrics = context.measureText(maxLengthString); if (metrics.width > maxLengthPixels) {
			// Trim the string to a max length.

			// The number of characters to remove.
			let removeChars = 1;   // At this point the length is too long, so remove 1 character to get it under.
			if (removeExtraChars > 0) {
				removeChars = removeChars + removeExtraChars;
			}
			removeChars = removeChars * -1; // To make sure they're sliced from the end.

			// Remove characters from the string.
			maxLengthString = maxLengthString.slice(0, removeChars);

			return maxLengthString;
		}
	}

	// Full string is OK.
	return maxLengthString;
}

JavaScript helper: getTextWidth [TypeScript]

Here’s a quick JavaScript helper snippet to calculate width of a string, based on a supplied font styling.

Written in TypeScript.

Credit goes to https://stackoverflow.com/questions/118241/calculate-text-width-with-javascript/21015393#21015393

/**
 * Uses canvas.measureText to compute and return the width of the given text of given font in pixels.
 *
 * @param {String} text The text to be rendered.
 * @param {String} font The css font descriptor that text is to be rendered with (e.g. "bold 14px verdana").
 *
 * @see https://stackoverflow.com/questions/118241/calculate-text-width-with-javascript/21015393#21015393
 */
private getTextWidth(text: string, font: string): number {
	// re-use canvas object for better performance
	let canvas = document.createElement("canvas");
	let context = canvas.getContext("2d");
	context.font = font;
	let metrics = context.measureText(text);

	return metrics.width;
}

JavaScript helper: GetElementInnerWidth [TypeScript]

Here’s a quick JavaScript helper snippet to get the inner width (excluding padding) of an element in the DOM.

Written in TypeScript.

/**
 * Return the calculated inner width of an element.
 * Returns -1 if width is unknown.
 * @param elementID         ID of the element to calculate the width for. Set to "" to use elementClassName
 * @param elementClassName  CSS class name on the element to calcualte the width for. Ignored if elementID is provided.
 */
public static GetElementInnerWidth(elementID: string, elementClassName: string): number {
	let width: number = -1;
	let element: any = null;

	// Get the DOM element to check,
	if (elementID !== "") {
		// Lookup by element ID.
		let elementByID = document.getElementById(elementID);
		if (elementByID !== undefined) {
			element = elementByID;
		}
	} else {
		// Lookup by CSS class name. Use first found node as actual element.
		let elementByClass = document.querySelectorAll("." + elementClassName);
		if (elementByClass !== undefined && elementByClass && elementByClass[0]) {
			element = elementByClass[0];
		}
	}

	if (element !== null) {
		// The outer width of the element
		width = element.clientWidth;

		// Get the calculated padding so we can remove it.
		let paddingLeft = ComponentHelpers.TryParseInt(window.getComputedStyle(element, null).getPropertyValue("padding-left"), 0);
		let paddingRight = ComponentHelpers.TryParseInt(window.getComputedStyle(element, null).getPropertyValue("padding-right"), 0);

		// Innerwidth = outerwidth - padding
		width = width - (paddingLeft + paddingRight);
	}

	return width;
}

JavaScript helper: TryParseInt [TypeScript]

Here’s a quick JavaScript helper snippet to test a string and return a parsed integer value, or a default value if the the parse fails.

Written in TypeScript.

 

/**
 * Try to parase an integer value from a string. Returns the number if successful, otherwise return a default value.
 * @param value The string with an integer to parase.
 * @param defaultValue Default value to return if parsing fails.
 */
public static TryParseInt(value: string, defaultValue: number = 0): number {
	let parsedValue = parseInt(value, 10);

	if (isNaN(parsedValue)) {
		// Failed to parse. Return the default value.
		return defaultValue;
	} else {
		// Return the parsed value.
		return parsedValue;
	}
}

Turn ASCII list of text URLs into HTML list of hyperlinks (with Regex and Notepad++)

I have a plain-text (ASCII) list of URLs, with each URL on a new line, and I need to turn it to a HTML list (<ul>) of actual anchor links (<a>).

For example, I start with:

https://www.site1.com/
https://www.site2.com/
https://www.site3.com/
https://www.siten.com/

And want to end up with:

<ul>
<li><a href="https://www.site1.com/">https://www.site1.com/</a></li>
<li><a href="https://www.site2.com/">https://www.site2.com/</a></li>
<li><a href="https://www.site3.com/">https://www.site3.com/</a></li>
<li><a href="https://www.siten.com/">https://www.siten.com/</a></li>
</ul>

In Notepad++ It’s trivial.

  • Paste your list of links into a new document.
  • Open the “Find” dialogue (Ctrl+F).
  • In the “Search Mode” options select “Regular expression”.
  • For “Find what” enter: ^(.+)$
  • For “Replace with” enter: <li><a href=”\1″>\1</a></li>
  • Select “Replace All”.
  • Then you just have to add the “<ul>” and “</ul>” on the first and last lines (respectively).

That’s it.

And here it is with images:


Image 1: The ASCII list of links.


Image 2: A clearer view of the FInd/Replace interface.


Image 3: The result of “Replace All”.

Don’t forget to add the “<ul>” and “</ul>” on the first and last lines.

(Update – 5 minutes later): I just noticed I can set the transparency of the Find/Replace dialogue, so didn’t need the second image. Oh well…)