I'm having problems in several cases when attempting to update data / onscreen controls and then use these controls with jQuery, especially images. My present case is the following:
button click ---> call angularJs function that creates div controls on the screen ---> angularJS function at the end call JS function ---> JS function call JQuery selectors for the created divs.
The problem is that JQuery can't find the created divs.
What is the best/indicate solution for this case? (not only for this case, but for the cases where we need to wait for the dom render complete)
Regards.
There could be several cases that could apply depending on your implementation. First make sure jQuery doesn't override angularjs functionality or vice versa. Second angularjs makes any JavaScript code in script tags invalid. You have to include your JavaScript in your controllers. You can use debugging tools like Firebug to see what's going on. Posting some code here would also help a lot.
Related
I just started learning AngularJS and I'm not really familiar with the terminologies in AngularJS yet. Here's my concern, I created a Loading Animation that shows up when I go to pages, but then I want to stop the Loading Animation as soon as all the contents of the pages has loaded. It's fairly easy to do in plain jQuery since I can just trigger $(window).load() but it doesn't seem to work in angular. $(document).ready() seems to work but that's not what I actually need since it gets triggered even though the images are not finished loading yet. I already tried $scope.init inside my controller as well as $window.onload inside my controller but I still can't make it work.
Hotfix answer
Actually you do not need to wait for any of these events in angular.
Just use $().. in your angular controller - the site was already loaded. (similar to the window.load() event. In case jquery does not find the html elements please try to wrap it with $timeout( function() { ... } );
Recommendation
Please do not! There are angular ways to animate stuff which fits better than crazy $('#id'). logic. This will break in growing applications.
I would recommend you forget about jQuery when you are working on AngularJS application. So figure out how to work everything out in AngularJS way - move all jQuery logic that you have to angular controller and avoid direct DOM manipulation (jQuery way).
Also, there's a good tutorial online if you are moving to AngularJS from jQuery:
https://gabrieleromanato.name/introduction-to-angularjs-for-jquery-developers
If you need a solution for switching pages go with ui-router - it will give you even more flexibility with loading pages and resolving properties for different pages:
https://github.com/angular-ui/ui-router
And in this particular case you can use simple boolean property on $scope and show preloader div based on that:
<div ng-show="showOverlay" class="loader" />
then inside your controller you could put something like:
$scope.showOverlay = true;
and then after your page logic is loaded and promises are resolved you could just hide that preloader with:
$scope.showOverlay = false;
To illustrate I created simple fiddle with preloader for you. Also keep in mind there are tons of different ways of implementing this but this is simple one that should work for almost any case:
https://jsfiddle.net/pegla/ng1mn8qp/3/
There's also one answer here on stack overflow that could help you:
How to execute angular controller function on page load?
I just got thrown into the Umbraco ASP.NET CMS for my latest project, I'm not sure if this is how it across the board but for my setup Knockout.js is doing all the templating.
I'm not too keen on knockout.js but so far it's been pretty straight forward except for when I start adding in some jQuery stuff, the problem I'm having is jQuery is firing before knockout has finished populating the page with all the elements.
The only solution that's worked for me thus far is all my jQuery stuff is wrapped in the setTimeout() function, which obviously is no good.
What's the most efficient way to make jQuery and Knockout work together so jQuery doesn't before knockout is done?
I recently had the same issue with the jSignature plugin and my Knockout view. I needed the KO view to have fully rendered before I invoked jSignature, otherwise it didn't size itself correctly.
I fixed it with a template binding and an afterRender callback function to invoke the jQuery work.
Here's the KO docs:
http://knockoutjs.com/documentation/template-binding.html
Here's a quick jsfiddle showing how you can use it:
http://jsfiddle.net/PCbFZ/
The trick is that you can use the afterRender callback of the template binding without actually using a template itself. Instead, you wrap all your existing HTML in a div that will invoke the afterRender callback:
<div data-bind="template: {afterRender: initApp}">
<!-- your existing HTML here -->
</div>
initApp is the function that does the jQuery work.
I think that should generally do what you need, though if your HTML is particularly complex, or you have many views you need to render inside the one page, you might need to do a bit more work. Let me know how you get on - maybe I can try to help a bit more if this doesn't quite fix your issue as easily as it did mine!
Update - following the comment from JACL below - here's an extended version of the fiddle showing this technique also working with ko-if. Each time you show/hide the 'widget' using the checkbox, a different random colour is applied to indicate the afterRender function doing its work.
http://jsfiddle.net/PCbFZ/15/
You might use:
$(window).load(function(){ /* code */ }); instead of $(document).ready();
Perhaps window.load instead of document.ready will do the trick
I have proof of concept imagemap code using angularjs here.
I am writing something to behave the same as the jquery example that I put together here.
You'll note in the first example doesn't work because the imagemap is being populated by a scope variable, so on page load the image src is a 404. This prevents the imagemap from activating at all. I would really appreciate help understanding how to fix this problem.
I used the $timeout service to wait for the DOM to be rendered as described here: Slick Carousel with Angular JS
However, I needed to specify an actual timeout value as the default didn't work in my case (for both slick and mapster)
I have some code that I'm using to create a dropdown menu that changes depending on what is checked. The JavaScript and html separated from the page work fine but once its loaded at the same time as the jQuery and everything is placed into a dialog box I receive an error which is like this
I can see this error thru Firebug on my client but it doesn't seem to appear in jsfiddle but when it appears the dropdowns don't work ...
document.form1a.damage is undefined
[Break On This Error]
document.form1a.damage[i].options.length=0;
I have managed to work out this much: that its caused by the dialog box part of the jQuery code, not the other jQuery that I'm using and that once the dialog boxes are removed the dropdown menus work absolutely fine. I have uploaded all me code to JsFiddle
Jsfiddle
Your form is empty when that code executes. Jquery ui dialog will move its entire html structure into its own div (typically at the bottom of the page) with all the applied styling, classes, etc.
To see this in jsfiddle, change the code load event to no wrap (head), it's above the framework select. You will get the error you mention.
Use firebug/chrome inspector to look at the html structure at that time. You have:
<form name="form1a" method="post" id="form1a"></form>
<div dialog1></div>
<div dialog2></div>
<div overlay></div>
As a solution to the issue, consider giving the selects their own id's and using:
document.getElementById('selectDamage0').options.length = 0;
... or continue using the by class name and index, etc instead of using the form notation.
Update:
Here is a jsfiddle showing another approach, just binding the onchange with jquery and setting the options through that. Commented a bit to show flow -- the function is near the bottom:
http://jsfiddle.net/xCMU6/
Update 2:
An old way of managing id's at the base level this way is to use a common prefix/suffix. So your first select is type-0 with damage-0. Then to reference the other you swap out the words (or split on -).
The problem is that jsFiddle is wrapping your code in a $(window).load function which makes fill_damage a variable defined in the $(window).load function. Once the $(window).load function has finished executing, the fill_damage function is no longer in scope, which means you cannot use an onchange handler to reference it.
The solution to this is to either:
include it in your $(function) and assign it to a click handler using jQuery (recommended since you're already using it) or through more traditional JavaScript methods (like addListener (not recommended since you're already using jQuery).
or to change your framework selection to noWrap (head) or no wrap (body).
I re-wrote your fiddle (with a lot of comments). You can see it here: http://jsfiddle.net/9YTwv/7/
Hope this helps.
I'm working on an website with some dynamic jQuery content.
If the user pushed a button ("show menu") on the page, an javascript function runs. Let this function call loadMenu().
The loadMenu() function loads a menu (web conent) from server using ajax. Part of this loaded code is javascript/jquery. 2 functions of this code make some elements on the page draggable, 2 other functions make some elements on the webpage droppable. These functions are all started at $.ready-Time (if the DOM is ready).
All this works fine.
Now i added an "MenuAlwaysVisible" feature. This means: if the web-page is loading and finished (ready) the user doesn't need to press the button "show menu", because the javascript loadMenu() now fires automatically, if the page is ready
The problem now is, it looks like, the draggable handler are attached and worked as defined, but droppable does not work.
I'm not sure, but probably the droppable function runs on a time, where the DOM elements doesn't like to be droppable? Ore maybe some other jQuery codes overrides this? (but there are no other droppable elements on the page)?
So the question is: how to analyze that problem: how to debug DOM manipulation, using Windows and Firefox/Firebug or Safari, Chrome .. whatever...
Thank you!
One debugging trick I have found endlessly useful for dealing with JQuery is the insert obvious code trick. Slap in a .hide() command on some obvious, identifiable part of the page, and see if the code ever runs. Lets you track which code pieces are not behaving as intended, and which are simply never being used in the first place.
To answer my own question: i did not found any alternatives way than using firebug and console.info() or console.warn() to debug the code.
Thanks # all for the comments