write custom function for navigation angularjs - javascript

So I have a navigation that I want to have a dropdrown menu with sub-menu functionality on it. I tried ng-show for showing and hiding the menus but then I would have to go back and click on item again to hide it. I want to be able to click to show, then click anywhere else to hide it.
trying to use ng-click but not sure where I should put my custom function that I want to retrieve regardless of the controller being used.
Would I put something like this in a directive? The function is not calling html or getting any content like a factory is generally for, it simply shows and hides content on different click events.

There are probably more complicated ways of doing this that might be more elegant, but I've found this to do the trick in the past. Assumes you're loading jQuery before Angular so $ is full jQuery. If you're finding yourself doing this with many different DOM elements though, it might be more effective to break this out into a factory that allows many objects to register themselves in this way with just one binding to body.
app.directive('clickOffHide',function() {
return {
...
link: function(.., elem, ..) {
$('body').click(function(evt) {
var $elem = $(elem);
var $target = $(evt.target);
if($elem.is($target) || $elem.has($target).length > 0) return;
$elem.hide();
});
}
}
});

You could try using ng-blur on the drop-down element.
<div ng-class="dropDown" ng-blur="functionToHideElement" tabindex="100">Products</div>
A div element can accept a blur event if it has a specified tabindex.
This way you can use a baked in Angular directive rather than creating your own.

Related

Assigning JQuery On Click Function in For Loop

I have a function that dynamically creates div elements based upon whatever input is given, and lets them choose certain items by clicking on each div. I have it so that if the div is clicked, a function (named checkToggle) is called that makes it looks like it is selected and adjusts some related variables. There is a checkbox in the div element that is toggled by this function (hence its name). Long story short, I had to jump through some hoops to get it to work, most of which I don't even remember. Please don't ask me about that.
The point of this question is this. I initially used the following JavaScript code to run the function when the checkbox was clicked. It was assigned by the main function, which created these div elements using a for loop.
document.getElementById(`${itemID}-checkbox`).onclick = function() {
checkToggle(`${itemID}-checkbox`);
};
This works, but I wanted to try to convert all of my onClick functions to JQuery. Here is the JQuery alternative I created.
$(`${itemID}-checkbox`).on(`click`, function() {
checkToggle(`${itemID}-checkbox`);
});
While the code itself seems to be fine, it does not work. It seems as if JQuery functions cannot be created like this in a for loop or something. It is applied after the element is created and put in its place, so I don't think it has anything to do with the element not being ready. I am also having the same issue with 2 other similar cases. Any idea as of why this isn't working?
Let me know if more information is needed and if so, what kind of information is needed.
You need to update the selector to Target HTML id using the # character. Simply prepend the character to the query:
$(`#${itemID}-checkbox`).on(`click`, function() { checkToggle(`${itemID}-checkbox`); });
It would also apply to DOM methods querySelector or querySelectorAll as well.
Hopefully that helps!

trying to add click inside a re-usable directive to a element that may have different classes be different element and may have different text

so here is the desire: I need to add a directive to any html element and pass it an id. This id is then used to populate a method that submits a form that has that id on the page.
Some devs have used a button some have used an anchor tag so I do not want the type of element to be part of the method. It is intended to be highly re-usable.
I already have it working like this:
angular.module("App").directive("submitform", submitFormDirective);
function submitFormDirective(){
return {
restrict: 'A',
scope: true,
link: function($scope, $element, $attrs){
var selector = $attrs.submitform;
$element.on('click', function(){
angular.element(selector).submit();
});
}
}
}
But this uses jquery for the "on" method. I want a fully angular method. Or one that does not "fight" with the framework or use jquery.
The way I am doing it now I only need to apply this attribute to the element. submit-form="#id-of-form" And I would like to keep that functionality becasue it is clean and concise. So I need to be able to add the ng-click to the element dynamically without using the limited template function which would limit the element being effected, inside the submitFormDirective.
The problem is that the $attrs.$set('ngClick', 'submitForm()') runs after the digest and $compile does not seem to work for me. I need to be able to add the click and run the compile on only this element or use a different phase that will happen before the app compile will run. But I have tried using compile to att the attr in conjunction with link adding the method to the scope to no avail. Seems strange that you would not be able to add a event from a directive. I must be missing something. Can someone help?

Change parent container in angularjs with ng-click

I have two separate containers, in one of them I have button. After clicking on it, this button must append to the second container. I understand how to make it in Jquery way:
$(document).on('click', '.drag', function(){
if($(this).parent('#dragplace').length)
{
$(this).appendTo('#dropplace');
}
else if($(this).parent('#dropplace').length)
{
$(this).appendTo('#dragplace');
}
});
But maybe angularjs have his own way to do that?
you can add one custom directive to the button. In the link function of the directive, you can bind events. you can use the same set of jquery codes there.
insted of '$(this)' you can use $(element). // element is the argument to the link function

jquery: dynamically appending li items to ul then adding click, but click runs through each li

So I may be approaching this wrong as I am learning but I can't seem to figure out what I am doing wrong here (probably simple mistake but I am having trouble). So I am trying to have a within the markup, a button click that allows selection from dialog and the submit button on the dialog includes call to custom function that does some logic then appends string to the like:
buildListElementItem += "<li>something</li>";
$("#my-list").append(buildListElementItem);
then bind click because i need each of these list items to be representative of a selection panel type thing
$("#my-list li").bind('click', function () {
//processing stuff
});
everything works fine but if I add more than one item to this list (one after another) and you click a single item, it rolls through each one, which confused me because there is no each and I think this should only add it to a single item....
so there is a bunch more to this function/etc but I think my approach right here is wrong??
I have tried modifying the selector to like a class that I add in the string for the li, I have tried using .on, .live, .delegate or anything I could find instead of bind click.
Perhaps this is simple approach type error to trying to perform this but I would great appreciate any help, advice, etc on this.
EDIT: just adding more for clarification
Dialog allows users to select item from select/drop down, and button click (jquery ui) has function that calls below idea to add the item to a list element, which serves as selection panel. So they can populate items needed on panel, then click each item to populate and associate data with that item.
function addNewListItem(passedType)
{
var buildListElementItem = "<li>" + passedType + "</li>";
$("#my-list").append(buildListElementItem);
$("#my-list li").bind('click', function () {
otherStuff();
});
if I do the above I am guessing that this cause every element to get binded over and over again? not sure, but this works with the exception that when I click a single li item on that panel, it processes for all li items on the panel (otherStuff function). So I think from the examples I am starting to understand the issue or why this won't work, but how would I approach what I am trying to do then? always appreciated guys!
}
When you say "there is no each", you omit that $("#my-list li") is a jQuery selector, i.e. it returns all the elements that match the expression: in this case, all the li items within the child tree of #my-list.
Thus, when you call bind, it is going to bind to each li item that has already been added to the element.
What you are looking for is something along this:
buildListElementItem = $("<li>something</li>"); //constructs a jquery object you can bind to
buildListElementItem.bind('click', function () {
//processing stuff
});
$("my-list").append(buildListElementItem);
This way, you bind before the element has been added.

using jQuery to change, only the elements that were loaded via ajax

For each checkbox on the web page, I replace it with a slider that I borrowed from jsfiddle.net/gnQUe/170/
This is done by going through the elements when the document is loaded.
Now the problem is that when more content is loaded via ajax, the new checkboxes are not transformed.
To solve the problem, I used AjaxComplete event to go through all the elements again and replace the checkboxes with sliders.
Now the problem happens that elements that were already replaced, get two sliders. To avoid that I check if the checkbox is hidden and next element is div of class "slider-frame", then don't process the re-process the element.
But I have a lot of other such controls as well, and I am presume I am not the only one that has this problem. Is there another easy way around it?
There exists jQuery live/on( http://api.jquery.com/on/ ) event but it requires an event as an argument? whereas I would like to change the look of my controls when they are rendered.
Another example of the same problem is to extend some controls that are loaded via ajax with jQuerys autocomplete plugin.
Is there a better way to accomplish this other than changing some attributes on the element.
To summarize, on document load I would like to process every element in DOM, but when more elements are loaded via ajax then I want to change only the new elements.
I would assume that when the element's are transformed into a slider, a class is added to them. So just add a not clause.
$(".MySelector").not(".SomeClassThatSliderAddsToElement").slider({});
So in the case of your code do something like this
$('.slider-button').not(".sliderloaded").addClass("sliderloaded").toggle(function(){
$(this).addClass('on').html('YES');
$('#slider').val(true);
},function(){
$(this).removeClass('on').html('NO');
$('#slider').val(false);
});
Since you said you do not want to add anything else, how about you change the toggle function to click.
$(document).on("click", ".slider-button", function(){
var elem = $(this);
elem.toggleClass("on");
var state = elem.hasClass("on");
elem.text(state?"YES":"NO");
elem.parent().next().val(state);
});
Running fiddle: http://jsfiddle.net/d9uFs/

Categories