I jsut started learning angular.js. Can you guys show me the right way to make a page that initially presents an ajax loader element saying 'Loading data' or something like that. Then after data's been fetched it would update the view and hide the element. I can put stuff in page load event using jquery, but how do you do that using pure angular? So far I figured out how to put that in click event:
<div ng-app="VideoStatus" ng-controller="VideoStatusCtrl">
<button ng-click="getVideos()">get videos</button>
</div>
<script type="text/javascript">
angular.module('VideoStatus', ['ngResource']).run(function(){
// I guess somehow I can start fetching data from the server here,
// but I don't know how to call Controller methods passing the right scope
});
function VideoStatusCtrl($scope, $resource) {
$scope.videoStatus = $resource('/Videos/GetStatuses', { callback: 'JSON_CALLBACK' });
$scope.getVideos = function () {
$scope.videoResult = $scope.videoStatus.get();
console.log('videos fetched');
};
};
</script>
Kudos to Adam Webber & Peter Bacon Darwin
Here is the working plunker
Here is my version plunker that make loading as a directive with modal popup feature
Here is the tutorial to use my version
you only need loading.js and modal.js and reference jQuery and twitterbootstrap css.
in your code,
Only 2 steps you need to do with your code.
Add the following code to HTML
< div data-loading> < /div>
Add LoadingModule module to your application module.
angular.module('YourApp', ['LoadingModule'])
Related
I would like to know which is the proper way to navigate between pages using ajax calls.
An example, we got this 3 html pages.
users.html (with users.js which initializes it and has its own functions)
cars.html (with cars.js which initializes it and has its own functions)
bills.html (with bills.js which initializes it and has its own functions)
What would be the proper way to go from users.html to cars.html ? I got this problem because I dont know how to "load" the cars.js after doing the ajax call in users.html.
¿If I load it with $.getScript(), how can I remove the users.js after adding the cars.js?
Thanks.
You can try to build a SPA (Single Page Application). You will have one index html file that uses the other html files as templates. For example you have a div main container whose content is replaced with users.html/cars.html/bills.html upon clicking a link.
Routing helps you get that done without refreshing the page. It also supports history.
Look up dependency injection so that you learn how you can download only the js files you depend on.
If you don't use routing and you only change the page content you lose history which is a really neat thing to have.
SPA with Routing and Templating
Routing with Sammy.js
Examples:
<body>
Cars
Bills
<div id="wrapper"></div>
<script src="jquery.js"></script>
<script src="sammy.js"></script>
<script>
(function() {
app.router = Sammy(function () {
var selector = '#wrapper';
this.get('#/cars', function() {
$.get('cars.html', function (view) {
$(selector).html(view);
});
this.get('#/bills', function() {
$.get('bills.html', function (view) {
$(selector).html(view);
});
});
});
app.router.run('#/cars'); //Link to load on app opening
}());
</script>
</body>
You can call page with $.get() like
$.get( "cars.html", function( data ) {
$(document).html(data);
alert( "Load was performed." );
});
In cars.js use all functions with $(document).ready()
but all functions must be:
$(document).on("yourevent","selector",function(){
});
while you load page cars.js will load if you import it in cars.html page
Read more about jquery.get() and jquery.on()
I am using Lean Modal: http://leanmodal.finelysliced.com.au/ in a Rails app with a React front-end.
When I put the link to the modal in application.html.erb it works fine but when loaded through a React link using the same code, nothing happens.
I have jQuery loaded and checked 10 times if the code is the same. What could cause such an issue?
Here is the link code in React:
<a rel="leanModal" name="login" href="#login">
The template file (html.erb) script:
<script type="text/javascript">
$(function() {
$('a[rel*=leanModal]').leanModal({ top : 200, closeButton: ".modal_close" });
});
And I am loading the modal JS from my application.js file in Rails.
Thanks for any help!
You should wrap things that interact with DOM (e.g. jQuery plugins) in a component.
var LeanModal = React.createClass({
componentDidMount: function(){
$(this.getDOMNode()).leanModal({
top: this.props.top || 200
});
},
render: function(){
return <div>{this.props.children}</div>;
}
});
Note that you also need to provide a componentWillUnmount to handle clean up, and that the plugin can't do things like add/remove elements. Plugins that don't allow cleanup or make destructive changes are incompatible with react.
Sometimes implementing it with just the existing CSS and using react components instead of the jQuery plugin can be very simple and end up with a better result.
Hi im trying to make a simple feed reader using ember.js and feedek. But so far when I try to place the code for the feed, it not working.
Jquery code for feedek (inside the index template in a script tag):
$('#divRss').FeedEk({
FeedUrl: 'http://vikinglogue.com/feed/',
MaxCount: 100
});
Html Code for template:
<script data-template-name="index" type="text/x-handlebars">
<article style="background-color:#fff;" id="divRss"></article>
</script>
When I run this code in the browser, nothing in the template shows up and I'm not getting any errors. I think the issue is caused by not linking feedek in the template but when I tried it, nothing happened. Thanks, any help is appricated.
To use a jQuery plugin in an Ember app, it's usually best to wrap it in a component:
App.FeedEkComponent = Ember.Component.extend({
tagName: 'article',
didInsertElement: function() {
this.$().FeedEk({
FeedUrl: 'http://vikinglogue.com/feed/',
MaxCount: 100
});
}
});
Then in one of your Handlebars templates,
<p>Your feed:</p>
{{feed-ek}}
I would add to Sam's excellent answer as follows:
Make the component reusable by passing in the url as a property
Don't override didInsertElement hook, instead specify that the function should run on 'didInsertElement' event (see here)
http://emberjs.jsbin.com/boguwagisi/1/edit?html,js,output
I have a simple website that implements jQuery in order to create a Slider with some images in the Index.html top banner.
Now, I want to use AngularJS so I'm breaking the HTML code into separate partials.
Header
Footer
Top Banner
If I run the Index.html in the original version (without applying AngularJS patterns) then I can see the slider working perfect.
When applying AngularJS patterns, I moved the top banner HTML to a partial html and then applied ng-view to the div where the top banner is originally located.
var app = angular.module('website', ['ngRoute']);
app.config(function($routeProvider) {
$routeProvider.
when('/about',{templateUrl:'app/partials/about.html'}).
when('/contact',{templateUrl:'app/partials/contact.html'}).
otherwise({redirectTo:'/home',templateUrl:'app/partials/home.html'})
});
When I refresh the page the slider is not working, is rendered as simple html without any jQuery effect, is really a mess.
This partials has some jQuery plugins that usually activates by document.ready. But this event not fire when angular load partial in ng-view. How can i call this event to initialize jQuery plugins?
Any clue how to fix this?
Appreciate any help.
When you specify your routes, you can also specify a controller, so your routes would look like this:
var app = angular.module('website', ['ngRoute']);
app.config(function($routeProvider) {
$routeProvider.
when('/about',{templateUrl:'app/partials/about.html', controller: 'aboutCtrl'}).
when('/contact',{templateUrl:'app/partials/contact.html', controller: 'contactCtrl'}).
otherwise({redirectTo:'/home',templateUrl:'app/partials/home.html', controller: 'homeCtrl'})
});
Now, you can define inside each controller what you want to do, jquery-wise, as part of a function, like this:
angular.module('website').controller('aboutCtrl', ['$scope', function ($scope) {
$scope.load = function() {
// do your $() stuff here
};
//don't forget to call the load function
$scope.load();
}]);
Make sense?
The other provided answers will work, but they are bound to controllers, and therefore not as scalable and reusable.
To do it the real "Angular" way as mentioned in the comments, you should be using a directive. The benefit to this is that you're able to create several instances with the same code, and can pass in attributes to the directive logic to "customize" the directive. Here's a sample of a way I've used it using bxSlider plugin:
JS:
app.directive('slider', ['$rootScope', function($rootScope) {
return {
restrict: 'EA',
templateUrl: '/path/to/template',
link: function(scope, iElement, attrs) {
//attrs references any attributes on the directive element in html
//iElement is the actual DOM element of the directive,
//so you can bind to it with jQuery
$(iElement).bxSlider({
mode: 'fade',
captions: true
});
//OR you could use that to find the element inside that needs the plugin
$(iElement).find('.bx-wrapper').bxSlider({
mode: 'fade',
captions: true
});
}
};
}]);
HTML:
<div slider some-attibute="some-attribute"></div>
And inside your directive template you could have the slider wrapper and slides, which you could build dynamically using ng-repeat bound to scope data.
I'd recommend reading this excellent article by Dan Wahlin about creating custom directives and how to fully harness they're power.
I had the same problem, I was loading some nav links in a ng-include and I have a script file called on my index.html with jquery instructions to make links active and It i not see the included content.
I tried all of the above solutions and for some reasons, none of them worked for me. When the content is not included (straight in the index.html) jquery kicks in fine but once included it stopped recognizing my elements.
So I simply wrapped my instructions in a setTimeout() function and it worked! Maybe it'll work for you too?
setTimeout(function() {
$("nav ul li").click(function() {
$("nav ul li").removeClass('active');
$(this).addClass('active');
});
});
Somehow the setTimeout() manages to load the script AFTER angular is done loading included content.
Happy coding everyone !
A Directive is certainly a good option, but you can also add a controller to any partial, which will perform all tasks (also with jQuery if you want) after the partial is loaded:
Example: partials/menu.html
<div ng-controller="partialMenuCtrl">
...
</div>
I had the same issue, I was running Jquery slick slider in simple html page it was working fine. How it works basically by including the slick.min.js file underneath the jquery.min.js file and then in script tags you need to initialize the plugin with options like e.g.
$('.items').slick({
infinite: true,
slidesToShow: 3,
slidesToScroll: 3
});
now coming back to the issue, when I added Angular JS to my page and made partials of the page and then went back to the browser to check weather the page was working fine or not, the page was working fine except the slider. Then I tried to move those slick.min.js and plugin initialization to the partials, and it worked :)
How it worked I don't know the reason, since I am new to Angular but it worked and I am still wondering the reason.
I know it is an old thread but just for the sake of completion, you can use the following JQuery code. It is called event Delegation.
$("#anyDivOrDocument").on('click', '#targetDiv', function(event) {
event.preventDefault();
alert( 'working' );
});
I bought a html5 template and tried to integrate with my angularJS web app. I encountered the same issue. I solved it using:
Put the code below at where you put your <script src="vendor/61345/js/script.js"></script> code.
<script>
document.write('<script src="vendor/61345/js/script.js"><\/script>');
</script>
I have social buttons from http://sharethis.com that I want to put on a profile page on my app. I'm using the ui-router for state management and page transitions, etc.
I've put the code I got from sharethis onto my index.html:
<script type="text/javascript" src="http://w.sharethis.com/button/buttons.js"></script>
<script type="text/javascript">stLight.options({publisher: "66053d76-64c6-4378-8971-aac043dbbc5d", doNotHash: false, doNotCopy: false, hashAddressBar: false});</script>
and the markup on my profiles page:
<span class='st_twitter_hcount' displayText='Tweet'></span>
<span class='st_facebook_hcount' displayText='Facebook'></span>
<span class='st_googleplus_hcount' displayText='Google +'></span>
What's happening is the social buttons are only loading when you refresh on the profile page (which is expected behaviour I guess). If the app bootstraps from say the homepage and then you transition to the profile page they aren't being loaded.
Are there any tricks that I can use to re-initialise or reload these javascript files?
I've spend some time investigating sharethis source code and found this function which creates buttons, on page controller add this function call and this will add the buttons.
stButtons.makeButtons();
While this might not be the best way according to documentation or best-practices, this was my solution. I had a particular view where I wanted a new set of ShareThis buttons to load. So I created a function which initialized the buttons again.
Here is the function which I placed in my controller:
$scope.loadShareThis = function() {
stButtons.makeButtons();
}
I then inititalize the function using ng-init in my html:
<div ng-init="loadShareThis()">
<share-buttons></sharebuttons>
</div>
This is probably not the answer, because you want to use shareThis, but I decided to use addthis, since I did not found a way to make shareThis work with angular.
Addthis enables asynchronous loading and dynamic rendering.
You can make it work like described here: http://support.addthis.com/customer/portal/articles/1293805-using-addthis-asynchronously.
And then you would probably want to make it into an angular directive, like described here: http://www.laurentiu-ciovica.com/2013/07/angularjs-addthis-directive.html
Answers by AlexG and Jeff Callahan gave me the direction, but it still didn't work for me. I had to wrap
stButtons.makeButtons()
in $timeout and now it works.
In HTML I have (JADE syntax)
my-directive(ng-repeat="review in myReviews" ng-init="loadShareThis()")
and in my controller I have
$scope.loadShareThis = function() {
$timeout(function(){
stButtons.makeButtons();
});
};
Has to do something with Angular digest cycles.