AngularJS use directive-name in scope as string - javascript

I have nested angular.js templates. Each template has it's own directive. Based of the data passed to the ParentTemplate, angular.js should call the matching directive.
<div class="parent-template">
<div class="{{childTemplate}}"></div>
<div class="template1"></div>
</div>
Lets say that $scope.childTemplate = template1. Both divs evaluate to the same content <div class="template1"></div> but only the second div calls the directive to show the template as expected.
I need a dynamic way to call the corresponding template directive
Here is the directive for template1
angular.module('myApp').directive('template1', function(){
return {
restrict: 'C',
templateUrl: 'templates/template1.html'
}
});
Directives for other templates directives work similar.

You try to set the class of the DOM element.
You can do this with ngClass.
Otherwise if you would like to set your directive as an attribute of the DOM element. Like this: <div template1> </div>
You can try this way:
var myEl = angular.element( document.querySelector( '#divID' ) );
myEl.attr('myattr',"attr val");

Try:
<div ng-class="childTemplate"><div>

Did you ever solve this? I have a similar challenge, which I currently solve by using ng-include, like so:
<div class="parent-template">
<div ng-include="'templates/template1'"></div>
<div class="template1"></div>
</div>
This works for your example, but gets more tricky when a directive does more than just wrapping a template, e.g. working with the DOM or adding a controller.
What you can do in that case is using the directive inside the template.
However, this feels all kinda hacky, i'd like a more direct approach
This was, for me, all sparked by an article on react plugins, in which you basically enumerate over a set of react component to get a feature set: https://nylas.com/blog/react-plugins

Related

Angular conditionally use directive attr inside directive template

I have a problem with using directive conditionally inside another directive,
so let's say I have one directive 'myGrid' and in it's template I have something like this:
<table my-grid-resizable>...</table>
and I want to use myGridResizable directive only if I use myGrid directive like this:
<my-grid resizable="true" />
But I don't want to use ng-if inside template of myGrid directive.
I tried this:
if (scope.resizable) {
angular.element(element).find('table').attr('my-grid-resizable', ''); }
But it's not working, attribute is added but directive is not working, recompiling directive is't helping as well.
Thanks for help in solving this
You're just setting the attribute, however, this does not mean that the DOM will be digested on it's own. The reason your DOM doesn't update is because you're not updating any model or binding. You're just modifying the DOM.
So you're gonna have to manually compile your element like,
First, inject $compile in your directive or controller (whichever is applicable)
Then do:
if (scope.resizable) {
angular.element(element).find('table').attr('draco-grid-dynamic-table', '');
var html = angular.element(element).find('table').html();
var compiledHtml = $compile(html)(scope);
angular.element(element).find('table').html(compiledHtml);
}
This way, however works, but is not an angular way and is highly discouraged.
I do not understand why you don't want to use ng-if structure. It is the angular way of doing things.

Ng-if on directives with two way bindings that override functions

I've set up a directive that will take in a function from the parent controller as one of it's attributes. This function will be replaced by the directives controller and will be accessible by the parent controller by using the passed function. The issue I'm running into is when placing an ng-if attribute on the directive the passed in function is not being replaced anymore. What causes this and how would I go about fixing this issue? I've attached an example
https://jsfiddle.net/dh7jt1zg/1/
<div class="parent" ng-controller="pCtrl">
<h3>Parent - with ng-if</h3>
<div>{{parentHelloWorld()}}</div>
<child ng-if="testBool" rep-fun="parentHelloWorld"></child>
</div>
<br/>
<div class="parent" ng-controller="pCtrl2">
<h3>Parent2 - without ng-if</h3>
<div>{{parentHelloWorld()}}</div>
<child rep-fun="parentHelloWorld"></child>
</div>
Use ng-show instead of ng-if.
ng-if causes element to remove from the DOM.
I think you'd be better off to create a service instead of replacing the function in the child controller. That seems kind of messy to me.
Personally, I'd use a service to register the function and then you can use that same service from the parent controller to call it.

Angularjs - is there a way to programatically click on an HTML <select> element?

I've seen a javascript solution that goes a little something like this:
var select = document.getElementById('selectId')
select.click();
Is there an AngularJS approach/best practice to the same thing? (Off the top of my head, you'd wrap the above code in an ng-click)
Yes there is. Here's the angular equivalent of what you have in JavaScript
angular.element('#selectId').trigger('click');
Working example
Any DOM manipulation in angular should occur inside of a directive.
View
<div id="selectId" clickMe>content</div>
Inside of a directive the link function triggers after the view is compiled. The second parameter in the link function is the element which the directive is placed on, this gives performance benefits since there is no need to traverse the dom. It is a JQlite element which you can directly call methods on.
Directive
app.directive('click-me', function(){
return{
link(scope, el, attr){
$(el).trigger('click');
}
}
});

Where and how to modify transcluded content?

I want to buid a directive (let's call it "A") that accepts HTML for transcluded content and modify its transcluded content by adding ng-click handlers on it using a custom logic.
I thought that the pre-link would be a good place to do this, but apparently I was very wrong (it seems that the docs suggest against it).
Every "A" directive will accept its own (unique) content, so I cannot do this in the compile phase.
In the link function I am not sure what I can do...
So, has anyone done anything similar?
EDIT:
I forgot to mention this: The handlers for ngClick should be defined on the directive's scope, not the parent scope. I don't know if Angular allows this, but that's what I need.
In your template you should add ng-transclude on the element want to add your custom html to.
your use of the directive:
<attribute ng-click="clickMe()">
<div>
transcluded data
</div>
</attribute >
and in your template:
<span ng-transclude>
</span>
Hope it makes sense :)

how to append div into one div using angularjs

<div data-ng-controller="maincontrol">
<div class="main">
</div>
<button data-ng-click="submit()">click</button>
</div>
when i click on click button i want to append one div within main div . i want to append one new div (dynamically)for each and every click .also i want to find whether children div exist or not .
i will do like this in jquery
$('main').append();
i will pass div within append();
but how to do by using angular..js ?
Using a directive could be a solution, but it's still too close to jQuery. When you play with Angular, you have to think differently.
jQuery is procedural.
1- I am finding an element in the dom
2- I am doing some stuff
3- I am adding, removing, updating elements in the dom
angular is declarative
You define your data
You define how your data should be displayed (using ng-repeat, ng-class, etc..)
then..
when you are playing with your data, the view is automatically updating.
If you want to play correctly with angular you should maybe do something like:
Template:
<div class="main">
<div ng-repeat="stuff in stuffs"><h1>{{stuff.title}}</h1> <p>{{stuff.content}}</p></div>
</div>
Controller:
function MainCtrl() {
$scope.stuffs = [];
$scope.submit = function() {
$scope.stuffs.push({title: 'Hello', content: 'world'});
}
}
It's generally best to create a directive for DOM manipulation ( many other uses for directives also).
Within a directive you have access to the angular.element . If jQuery is installed before angular.js in page, this is a jQuery object, otherwise it is a jqLite object that has many jQUery compatible methods.
Very simple example:
<button data-ng-click="submit()" my-directive>click</button>
app.directive('myDirective',function(){
return function(scope, element, attrs){
element.click(function(){
element.parent().find('.main').append('<div>Some text</div>')
})
}
})
Read up on directives and angular.element

Categories