ng-transclude does not work any more after JQuery update - javascript

This is a weird issue i have started to encounter after the latest JQuery update.
We use angularjs 1.7.9 in out app. We have following component. It is basically a date field wrapper .
export class DateFieldComponent {
...
transclude: any = {
iconContent: "?iconContent",
};
template: string = `
<div>
<span
ng-click="$ctrl.focusInput()"
ng-transclude="iconContent"
/>
<input
...
></input>
</div>
`;
}
angular.module("App").component("dateField", new DateFieldComponent());
As you can see, we use ng-transclude to load an icon on to the input field. We made it in this way so that whoever using this component can dynamically add the icon from the client side.
This component was working fine until we updated JQuery from 3.4.0 to 3.5.0 . After the update the dateField has issues. However there are no console errors. But i was able to pin point the issue to below line
ng-transclude="iconContent"
So if i remove this line, everything works fine. Adding this line back makes the component to not to render properly.
I know for a fact that JQuery update has no effect on angularjs cause angularjs uses its own jquery-lite version. Also as far as i know, ng-transclude has nothing to do with JQuery.
Also i noticed that there are similar issues in all the places we use ng-transclude in our app, after this update.
What am i missing here ? Any clue would be much appreciated.

Turns out we made a simple mistake in the markup which is not working anymore with JQuery 3.5.0 version
this was the culprit
<span
ng-click="$ctrl.focusInput()"
ng-transclude="iconContent"
/>
fix was to close the span properly like below
<span
ng-click="$ctrl.focusInput()"
ng-transclude="iconContent">
<span/>

Related

onsenui cannot change content

I’m using onsen ui version 1, followed https://onsen.io/v1/guide.html to make changes to DOM
This section to be exact
// Add another Onsen UI element
var content = document.getElementById("my-content");
content.innerHTML="<ons-button>Another Button</ons-button>";
ons.compile(content);
The problem is nothing changed on the page.
If i dump “content” variable or dump the HTML element it shows the newly edited version on browser console. but on page still the old one.
ons object is instantiated, compile method is callable, tried different HTML elements.
Either you are doing something incorrectly or it's an angular refresh issue.
For the first scenario it's easier if you provide a codepen, so that we can see the problem. Currently the code you are mentioning is working fine for me here.
For the second scenario actually the third line ons.compile(content); should remove this problem imo, it might be a version issue, or there is some context which I am missing.
If you're doing something angular related then you should also show where you are calling these 3 lines from. In order to work it should be called from something like an ng- event (for example ng-click).
JS:
app.controller('yourControllerName', function($scope) {
$scope.addButton = function () {
var content = document.getElementById("my-content");
content.innerHTML="<ons-button>Another Button</ons-button>";
ons.compile(content);
}
});
HTML:
<ons-button ng-click="addButton()">Add another button</ons-button>
Finally if you are unable to make it work you can do something like
app.controller('yourControllerName', function($scope) {
$scope.addButton = function () {
var content = document.getElementById("my-content");
content.innerHTML="<ons-button>Another Button</ons-button>";
ons.compile(content);
$scope.apply(); // should fix the issue, but not recommended
}
});
PS: You can also try out onsen 2 - there you can:
experiment with the interactive tutorial
try out the vanilla version (without any external framework) - which will not have issues like this one

Using templateUrl breaks my code, but using inline template instead works . Why?

Ok, I've seen similar questions on SO but still don't understand this issue.
I have a directive for date input, using ngModelController. I have another directive, to which you can pass the model controller, and it checks if the model has errors, and sets appropriate classes to the element.
So the markup looks like this:
<form name="myForm">
<div class-validation="myForm.date">
<date-input ng-model="date" name="date"></date-input>
</div>
</form>
Since we have date-input inside of our form, and it has the name attribute and ng-model, the ngModelController will be added to myForm under the name date, which is exactly what we pass to class-validation directive.
Now the problem is, if I use templateUrl for my date-input directive, the class-validation directive receives undefined. But when I use inline template instead, everything works as expected.
Here is a Plunker that demonstrates the problem exactly.
http://plnkr.co/edit/Cygawxjp4WN9xRbTEXWU?p=preview
Comment out line 41 and uncomment line 42 in script.js to see the problem. The validation doesn't work and if you open browser console, you'll see that class-validation parsed myForm.date as undefined.
Why is this happening? I am guessing that requiring template from an url is async operation, but it shouldn't make a difference to the developer. I wasted hours and hours trying to find out what's causing this. Thanks.

After using $sce.trustAsHtml, ng-click not working

I am trying to print to the screen custom html using angular. I am using $sce.trustAsHtml in combination with ng-bind-html to accomplish this. The goal is not only to be able to print this custom html, but that it will retain directives such as ng-click and they will be usuable. Examples I have seen in articles such as follows are promising:
AngularJS render HTML within double curly brace notation
However in my implementation I find that although the html renders correctly including references to ng-click, the directive doesn't seem to work anymore when trying to click on the link I am using it on; here is some sample code:
$scope.htmlExpression = $sce.trustAsHtml("<a ng-click='test();'>Click Me</a>");
$scope.test = function() {
console.log('Hello World!');
}
<div>
<p ng-bind-html="htmlExpression"></p>
</div>
As everything renders fine and nothing appears lost in translation when analyzing the source; I am left feeling as if I have left something out. Any help is appreciated.
Use https://docs.angularjs.org/api/ngSanitize and bind the html. If this does not work, $digest to reboot the digest cycle.

Angularjs animate ngClick + ngShow with custom directive (mySlide)

I'm trying to get the same ultimate functionality as ng-click + ng-show, except that I want the show to slide in instead of suddenly appear by toggling display: block/none;. I've got the jQuery animate I need, and I've set up the ng-click. I've got 2 problems, but the second might be a result of the first:
Problem 1
ng-click does not change the value of aside_users. I saw SO#12202067 which seems to be a similar situation, but I don't understand how/why their custom directive works and the native ng-click doesn't.
I see the scope: { … } after restrict: 'A',, but that appears to make $scope values available within the newly-created DOM element (my elements already exist and show up just fine, but no triggers/events are happening).
infobox.html
<aside
class="users"
ng-include src="'views/users.html'"
my-slide={"direction":"left","condition":"aside_users"}
></aside>
<i
class="icon icon-user"
ng-click="aside_users=!aside_users"
ng-init="aside_users=false"
></i>
The above code is a $compile'd template and elsewhere within the template I print out the value of the $scope parameter aside_users (prints false).
Problem 2
my-slide doesn't seem to be initiated/triggered (the logging of 'elm: ', elm doesn't appear in Chrome's console). I verified that directives.js is linked in my index.html page.
EDIT I remembered to link directives.js in index.html, but I forgot to add it to the resources array in app.js.
Plunkr
P.S. I'm not sure if <aside attr={object}> is strictly valid, but legitimate browsers seem to accept it in test cases (didn't bother to check IE). My alternate plan is to use 2 attributes: <foo my-slide="direction" my-condition="boolean"></foo>

AngularJS error when wrapping jQuery plugin in a directive

I'm working on a directive for AngularJS that builds a taggable element and utilizes TagsInput
Here's a working fiddle: http://jsfiddle.net/mgLss/
Not sure why but when I add that directive to my application IT works fine, but anything else below it running angular fails and I get this error message:
Error: node is undefined
compositeLinkFn#http://ajax.googleapis.com/ajax/libs/angularjs/1.0.2/angular.js:3837
compositeLinkFn#http://ajax.googleapis.com/ajax/libs/angularjs/1.0.2/angular.js:3837
nodeLinkFn#http://ajax.googleapis.com/ajax/libs/angularjs/1.0.2/angular.js:4216
compositeLinkFn#http://ajax.googleapis.com/ajax/libs/angularjs/1.0.2/angular.js:3834
compositeLinkFn#http://ajax.googleapis.com/ajax/libs/angularjs/1.0.2/angular.js:3837
compositeLinkFn#http://ajax.googleapis.com/ajax/libs/angularjs/1.0.2/angular.js:3837
compositeLinkFn#http://ajax.googleapis.com/ajax/libs/angularjs/1.0.2/angular.js:3837
nodeLinkFn#http://ajax.googleapis.com/ajax/libs/angularjs/1.0.2/angular.js:4216
compositeLinkFn#http://ajax.googleapis.com/ajax/libs/angularjs/1.0.2/angular.js:3834
compositeLinkFn#http://ajax.googleapis.com/ajax/libs/angularjs/1.0.2/angular.js:3837
compile/<#http://ajax.googleapis.com/ajax/libs/angularjs/1.0.2/angular.js:3746
bootstrap/</<#http://ajax.googleapis.com/ajax/libs/angularjs/1.0.2/angular.js:932
Scope.$eval#http://ajax.googleapis.com/ajax/libs/angularjs/1.0.2/angular.js:7808
Scope.$apply#http://ajax.googleapis.com/ajax/libs/angularjs/1.0.2/angular.js:7888
bootstrap/<#http://ajax.googleapis.com/ajax/libs/angularjs/1.0.2/angular.js:930
invoke#http://ajax.googleapis.com/ajax/libs/angularjs/1.0.2/angular.js:2788
bootstrap#http://ajax.googleapis.com/ajax/libs/angularjs/1.0.2/angular.js:929
angularInit#http://ajax.googleapis.com/ajax/libs/angularjs/1.0.2/angular.js:904
#http://ajax.googleapis.com/ajax/libs/angularjs/1.0.2/angular.js:14397
f.Callbacks/o#http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js:2
f.Callbacks/p.fireWith#http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js:2
.ready#http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js:2
B#http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js:2
I've spent the last hour on IRC but cant get any acknowledgment of my question so here's hoping Stack will come to the rescue as it has so many times before.
This is something related to the plugin you are using, it manipulates the dom in a way angular does not like it, I didn't to go into the source code the point you to the root of the issue, to be honest. But here is a way (an ugly one) to fix it.
<div ng:controller="TestCtrl">
{{ hello }}
<div><taggable default="changed"></taggable></div>
</div>
​
Just wrap that directive within another DOM element, making sure the plugin is isolated.
http://jsfiddle.net/mgLss/33/
Building on #fastreload's answer, a slightly less ugly solution, which does not require changing your HTML:
// as per #fastreload, wrap input in a div to prevent Angular from getting confused
template: "<div><input type=\"text\"></div>",
link: function(scope, elm, attrs) {
elm.children().tagsInput({ // note children()
You should also include Angular last in your fiddle (under Manage Resources) (and in your code in general), then elm is automatically a wrapped jQuery element, rather than a wrapped Angular element, and hence we don't need to use $(elm) in the link function.

Categories

Resources