i tried to implement turn.js in angularjs app, when i click a link it takes to the page having that turn.js at that time my custom directive is not loading. If i press F5 then the custom directive is loading and turn.js is working propely.
My custom directive is like this
app.directive "turnJs", ->
alert "loaded"
restrict: "A"
link: (scope, element, attrs) ->
$(element).turn scope.$eval(attrs.turnJs)
return
and my view is like this
<div class="butiknamncontainer" id="magazine" turn-js>
<div>
dfdssdfs
</div>
<div>
sdffsdfsf
</div>
</div>
is there any way to load the directive while doing that ng-click??
You need to include the directive definition one the first page of your app so that Angular knows what to do when it encounters the directive in your HTML.
The reason it works when you refresh is because Angular is being bootloaded along with the directive definition(Look at the hashtag in the URL).
Whereas when Angular is bootloaded without that file, such as when there is nothing in your hashtag, Angular has no idea what to do when it later encounters that directive. So, it gets ignored.
Related
I'm trying to get my head around the way angular does DOM element to DOM element communication:
We're putting together a set of e-learning templates. The first interactive components we've added are a bullet (effectively a button) and a popup. The bullet and the popup can be in separate parts of the page, so they will not be within the bounds of the same directive (although there is an over-arching pageCtrl, so they have that in common).
We've made custom attribute directives to trigger loading in each component type's html template; Here's the directive for eng-bullet:
app.directive('engBullet', function() {
return {
restrict: 'A',
replace: true,
templateUrl: 'components/bullet.html',
link: function(scope, element, attrs) {
// following function referenced in bullet.html
scope.showElementByUniqueName = function (showOnClick) {
// remove 'replaces' element
$('#'+$('#'+showOnClick).attr('data-replaces')).addClass('hidden');
// hide all popups (in case another popup is currently visible)
$('.popup').addClass("hidden");
// show selected popup
$('#'+showOnClick).removeClass("hidden");
}
}
};
});
At the moment the bullet component is given a 'show_on_click' string (from the json file that describes the page content) and this is passed to the bullet template (components/bullet.html):
<div class="button bullet" ng-click="showElementByUniqueName( component.bullet.show_on_click )"><p>{{component.bullet.text}}</p></div>
The 'show_on_click' variable corresponds to the id of the specific popup the bullet should display and this variable is then used in the eng-bullet directive to show the correct popup.
If I instead added an ng-show directive to my popup template, how would I bind that to the corresponding bullet which is on a different part of the page?
I could put the logic in pageCtrl, but then I've been told controllers should be 'lean and dumb'. How would I specify which popup to show, in the angular way?
Transclude fallback content is one of the features added to Angular V1.5.0
I'm writing a dateTimePicker module for Angular and want to add custom user input template feature for next version and Transclude fallback content is exactly what i want, because if user put nothing inside the directive, default template will inject.
But i can't force everyone to use Angular V1.5.X
Is there any alternative solution?
Another Solution:
As i have a huge html template and can't make it single line string or ... to put it in JS file, i forked Mario Lamacchia idea.
HTML:
<div>
<ng-transclude></ng-transclude>
<div ng-if="defaultTemplate">...</div>
</div>
JS:
link: function(scope, element, attrs, ngModel) {
if (!element.find('ng-transclude').children().length) {
scope.defaultTemplate = true;
element.find('ng-transclude').remove();
}
}
Adding this link function in 1.3.x version gives the same result of the 1.5.x example for transclude fallback content
link: function(scope, element) {
if (!element.find('ng-transclude').children().length) {
element.find('button').append('<b style="color: red">Button1</b>');
}
}
Plunker: http://plnkr.co/edit/7VHLsv
My angular app uses ngInfiniteScroll
angular.module('myApp',['ui.router', 'infinite-scroll'])
I load a partial into a ui-view directive. The partial has infinite-scroll set up on a ul element. This works fine and responds to data returned from an $http call invoked in a search service.
(This is a part of the Jade template partial)
div#results-container
div.intermediatediv
ul(
infinite-scroll="homeCtrl.searchMore()"
infinite-scroll-parent = "true"
infinite-scroll-distance="0"
infinite-scroll-container="'#results-container'")
li(ng-repeat="lot in homeCtrl.searchResults", ng-bind-html="lot.lotDescription")
Using a ui-sref anchor on this page and with ui-router I change the template part in the ui-view directive element.
a(ui-sref="home.<routeName>") <A link text>
The new template part does load and displays OK but there is no infinite-scroll directive within the markup.
So, I get this error in the Firebug console:
'elem.document is undefined'
Any thoughts about why this happens?
Thanks
I have built an app where I need dynamically change templates.
<div ng-include="templateUrl"></div>
I have two templates like addtext.html and addmedia.html. I dynnamically change it using angularjs. But in my addmedia.html template, I have filepicker's pick file widget.
<input type="filepicker" data-fp-apikey="..." data-fp-mimetypes="*/*" data-fp-container="modal" onchange="save_url()">
The pick widget does not load in the template. Is there any way to get it to work?
Well, I don't know much about filepicker.io, but as far as I understand, the problem is that widgets are constructed on page load. This means that when you switch templates, filepicker may not process them automatically, see documentation:
We'll automatically convert any widgets that you have on page load. However, if you want to create widgets once the page has loaded, you can... call filepicker.constructWidget(); method.
So, I would suggest you a simple directive that just puts an input tag with type=filepicker, and then linking filepicker to it using before mentioned method, like this:
app.directive('myFilepicker', [function() {
return {
transclude: true,
restrict: "E",
template: '<input type="filepicker">',
replace: 'true',
link: function(scope, element) {
filepicker.constructWidget(element);
}
};
}]);
and in your markup you can use it like this:
<my-filepicker data-fp-apikey="..." data-fp-mimetypes="*/*" data-fp-container="modal" onchange="save_url()"></my-filepicker>
See this demo. I don't have filepicker.io API key, but I hope this would work.
I'm trying to shove mixitup inside my angular page and in order to do so I made a directive module for it
angular.module('MainCtrl', [])
.controller('MainController', function($scope) {
$scope.tagline = 'To the moon and back!';
})
.directive('mixitContainer', function() {
return {
restrict: 'A',
link: function(scope, element, attrs) {
$(element).mixItUp(scope.$eval(attrs.mixitContainer));
}
};
});
Don't worry about the simplicity of the main controller, it is simply a test.
Now, the issue is that the directive only get's called once! If I go to another page and ask angular to load another controller and then go back to the home page and ask angular to load MainCtrl again, the directive isn't loaded!
Heres the with the directive:
<div id="Container" class="mixit-container" mixit-container="{load: {sort: 'order:asc'}, controls: {toggleFilterButtons: true, toggleLogic: 'and'}}">
Anyone got any ideas?
AngularJS doesn't include routing facilities. Those are provided either by ngRoute (a core but optional module), ui-router (ngRoute made super-awesome-amazing), or another replacement. You don't say which you use, and each has different behaviors.
Whichever it is, this is going to come down to the router, not the directive. The directive will get called whenever necessary. It doesn't control that itself - 'necessary' means Angular is compiling a portion of the DOM, usually from a template file, and has run into the directive. It will call the directive and ask it "what now?"
The above-named routers have different behaviors, both from each other and also based on how you configure them internally. In all of them you can arrange things so that templates do, or do not, get re-rendered. For example, in ui-router you can have 'child' states. If you have a child state active, the parent is also active... so going from the child to the parent will not re-render a template because it was already done earlier. And to make matters more complex, you can even override this by hooking the $stateChangeStart event and force the router to redraw that view even if it didn't think it needed to.
All this means... set your attention to your directive aside. It will do what you want as soon as the higher level does what you want. Get your router behaving the way you expect and you will be happy!