angularJs directive template removal - html

in every angular template we have to define a root html node, then inside it we can define the Html of our directive.
is there a way in angular to ignore that root node?
example :
my directive template :
<div class="space consuming div, and absolute positioning breaker">
<div class="content positioned relative to the directives parent 1"></div>
<div class="content positioned relative to the directives parent 2"></div>
<div class="content positioned relative to the directives parent 3"></div>
</div>
can we just set our template to be
<div class="content positioned relative to the directives parent 1"></div>
<div class="content positioned relative to the directives parent 2"></div>
<div class="content positioned relative to the directives parent 3"></div>
thanks!

You only need one root element if you are using replace: true in your template.
This is the case if you have defined custom element and are using then in your HTML in the following way:
<tabs>
<pane>1</pane>
<pane>2</pane>
</tabs>
In this case, replacing tabs with a template which has two roots will cause some confusion.
However, if you do not need replace: true, then you can set the directive on the element you want and assign a multi-root template on it. That template will be rendered inside the element which has the directive.
JS
var app = angular.module('plunker', []);
app.directive('myDirectiveOne', function() {
return {
template: '<p>Hello</p><p>World!</p>'
};
})
app.directive('myDirectiveTwo', function() {
return {
template: '<p>Hello</p><p>World!</p>',
replace: true
};
})
Template
<!-- works -->
<div my-directive-one></div>
<!-- has problem -->
<div my-directive-two></div>
E.g. http://plnkr.co/edit/jgEWsaxzfD4FkHcocJys?p=preview

Related

Appyling conditional css values in angular 8

I have a parent component and child component where I am using child component's selector to render it in parent component.
my child component html:
<div class="main-container" [ngStyle]="{'transform': 'scaleX(widthScale) scaleY(heightScale)'}">
<img src="../../assets/svg/kiln-main.jpg" class="kiln-image">
<svg id="area2"></svg>
<svg id="area"></svg>
</div>
child component ts:
#Input() widthScale:string;
#Input() heightScale:string;
I want to apply "transform:scalex() scaley()" to child based on the values from the parent.
my parent:
<app-child [widthScale]="0.5" [heightScale]="0.5"></app-child>
The above code somehow isnt working.How to apply values to css property "transform" here?
You can create a method in the child as follows:
getTransformStyle() {
let styles = {
transform: `scaleX(${this.widthScale}) scaleY(${this.heightScale})`,
};
return styles;
}
Use it in child html as follows:
<div class="main-container" [ngStyle]="getTransformStyle()">
<img src="../../assets/svg/kiln-main.jpg" class="kiln-image" />
<svg id="area2"></svg>
<svg id="area"></svg>
</div>
You can refer to the child as follows:
<app-child [widthScale]="'0.5'" [heightScale]="'0.5'"></app-child>
Working example: https://stackblitz.com/edit/angular-ivy-gaohfo

preventing a child from inheriting draggable" attribute in html

i have some <div></div> elements with draggable="true" attribute but same thing gets applied on child elements,but i dont want to apply it on child elements, So how do i prevent this default behavior?
code :
<div draggable="true" ondragstart="play(event)" ondrop="pause(event)" id="move">
<span id="text">
drag me
</span>
</div>
as i used dragable="true" on <div> so span also gets the same property.
I was having a similar event with a sortable drag-and-drop "list" I created. Each "row" of the list looks like this.
<div class='row' draggable='true'>
<div class='drag-handle' ></div>
<img class='icon-image' draggable='false'>
<input type='text' name='demo' >
<button class='remove-btn' onclick='removeItem(this,event)'>Remove</button>
</div>
When I tried selecting the text inside of the "input" element, somehow I would start dragging the whole "row". As frustrating as this was, the best solution I found was to simply apply the draggable='true' property to the item with the class="drag-handle" which would be my dragging icon that would fire the ondragstart(e) event.
The rest can be handled in JS
In JS, reference the parent element "row" by using the closest(".row") method
document.addEventListener("DOMContentLoaded", () => {
document.querySelectorAll('.drag-handle').forEach(handle => {
handle.addEventListener("dragstart", dragStart)
handle.addEventListener("drag", dragging)
handle.addEventListener("dragend", dragEnd)
})
function dragStart(e) {
document.querySelectorAll(".row").forEach(row=>{
row.addEventListener("dragover", dragOver)
})
var target_row = e.target.closest(".row")
target_row.classList.add("dragging")
}
Note:
I added a class of "dragging" to the one "row" that was going to be dragged so I could do a querySelectorAll('.row:not(.dragging)') for other operations, classes, etc, however, this is NOT required for the intended purpose to work. Just a bit more context that hope helps your problem.

Select an element in DOM which is not a sibling, but goes after

Let us suppose I have the following DOM
<div class="parent">
<div class="childNotSibling">
</div>
</div>
<div class="elementToSelect">
</div>
Now I would like to select the div with elementToSelect class but only if div with parent class has inside it an element with childNotSibling class. Is it possible to acomplish this using css?
This JSFiddle should do the trick: https://jsfiddle.net/tremor/f4cghd5x/
Using JQuery here is the Javascript portion of the code.
// find all the occurrences of .childNotSibling
$("body").find(".childNotSibling").each(function(index, element) {
// if .childNotSibling's parent has class "parent"
if ($(this).parent().hasClass("parent")) {
// and if the parent's next sibling has "elementToSelect"
if ($(this).parent().next().hasClass("elementToSelect")) {
// do something with that element
$(this).parent().next().css("background-color", "red");
}
}
});

Angular Directive Children without transclude parent

I'm working with Angular directives that looks like this:
<parent>
<children></children>
<children></children>
<children></children>
</parent>
Parent directive has a
template: return "<div><ul></ul><div ng-transclude></div></div>"
And children directives will go inside that ng-transclude div.
My final HTML structure is
<newParent>
<div ng-transclude>
<child></child>
<child></child>
<child></child>
</div>
</newParent>
I wonder if it's possible to remove that ng-transclude div so that the new children are direct children of the new parent. (I have more children, a random number >1).
I have to do so to match an existing template so I cannot change its structure.
I actually have no Fiddles, if you need more information just ask. Thank you!
You can append the content yourself, without using ng-transclude, using the transclude function:
app.directive("parent", function($compile) {
return {
restrict: "EA",
transclude: true,
link: function(scope, element, attrs, ctrls, $transclude) {
$transclude(function(clone, scope) {
element.append(clone);
});
}
};
});
Here's more information about Transclusion.
Without a template, this will add the transcluded elements as only children of the directive. With the template, you'll need to properly place (e.g. insert it into a <div> after <ul>) the content yourself.

DOM manipulation by angularjs direction

I read that Angularjs directives require a different approach than jquery. I am new to angularjs, so it will be great if somebody can explain how to use directives for this simple example. If you click on bottom div, then it moves (re-parent) the top image to the bottom div. I could add this jquery code on ng-click... but is there a better way?
JQUERY INTENT:
$("#bottom").click(function(){
$("#myimage").appendTo("#bottom");
});
ANGULARJS:
<div ng-app="myapp">
<div data-ng-controller="mycontroller">
<div id="top" style="background-color:red;width:200px;height:200px">
<img id="myimage" src="//placehold.it/150x150">
</div>
<div id="bottom" style="background-color:green;width:200px;height:200px">
</div>
</div>
</div>
Instead of listening for a click in jQuery, you can use Angular's ng-click directive to specify a function to call when the element is clicked and you can use the ng-if directive to add/remove the image, for example...
<div ng-click="appendImage()" id="bottom" style="background-color:green;width:200px;height:200px">
<img ng-if="showImage" id="myimage" src="//placehold.it/150x150">
</div>
Then in your controller...
angular.controller('myController', function ($scope) {
$scope.showImage = false;
$scope.appendImage = function (event) {
$scope.showImage = true;
};
});
A key difference between plain jQuery and Angular is that in jQuery you have to write code to manipulate the DOM yourself (like appending the image). If you use directives properly in Angular, you simply make changes to the $scope and directives will update the DOM for you automatically