I'm working on an eCommerce site and using angular to build a widget on product detail pages. I have very limited control over what is initially rendered as HTML for the browser. Most of what needs to be done with my widget is working as expected. I have a side effect of Angular's expression interpolation affecting the add to cart
form. Each of a product's color variations will render to the page as as HTMLOptionElement
with an innerText
value like one of the following:
{{hex="000000";sizes=["S","M","L","XL","2XL"];name="Black";}}
or
{{hex="FFFFFF";sizes=["S","M","L"];name="White";}}
or
{{hex="323C88";sizes=["S","M","L","XL","2XL"];name="Royal";}}
The end result of the Angular initialization process is that each of these is transformed into the following:
Black
orWhite
orRoyal
respectively
This is fine, as this allows the user a readable value for his color selection. The side effect is that the parent HTMLFormElement
no longer submits via the submit button. Its class attribute has been changed to include ng-pristine
and ng-valid
.
Please note I cannot change the HTML of this form until after the page loads.
I'm sure I could hack together a simple override to get the form to submit, but I'm looking more for information about plugging into angular's initialization. The best I've been able to come up with so far is to wrap the form with ng-non-bindable
in the java template:
<div ng-non-bindable>${MyAddToCartFormRendersHere}</div>
But then I'd need a way to do the $interpolate
call myself after the page had loaded.
This works but I'll bet there is a better way.
AngularApp.directive("customInterpolation", function ($interpolate, $document) {
$document.find("option:contains('{{')").each(function(i,el){
var angEl = angular.element(el);
angEl.text($interpolate(angEl.text(),true));
});
and then the form wrapper becomes:
<div ng-non-bindable data-custom-interpolation>${MyAddToCartFormRendersHere}</div>
My directive will run once, but returning anything (e.g. a link function) is useless because of the nonBindable directive. ... there has to be a better way.
Here is a jsfiddle to better illustrate the issue. Note, the form won't submit unless the ngNonBindable
directive is applied to the surrounding <div>
.
Write a directive with a compile function that finds the form
and modifies the action
attribute to include a ?
. The directive's compile function will execute before Angular compiles the form.
HTML:
<div modify-action>
<form class="product-border product-gap addtocart" method="post" action="">
Directive:
myApp.directive('modifyAction', function() {
return {
compile: function(element) {
var form = element.find('form');
console.log(form);
form.attr('action', '?');
console.log(form);
}
}
});
Fiddle. When you hit submit, you'll see that the form is submitted.