adding element with ng-click using angular.element - javascript

I am trying to add a couple of custom buttons to the right part of the header of fullcalendar (http://arshaw.com/fullcalendar/docs/).
I am using angular.element to add the buttons like this:
var calendarHeaderRight = angular.element(".fc-header-right");
if (calendarHeaderRight)
calendarHeaderRight.html('<div>CalendarList </div>');
The buttons do get appended to the calendar and are displayed. The problem is that nothing is happening when I click the buttons.
So the question is, how do I append elements which can be clicked ?
thanks
Thomas

var element = $compile(angular.element('<div>CalendarList </div>'))(scope);
then you can wrapped this element in your div. Here is angular document about compile.
: ) enjoy it.

var html = angular.element('<div>CalendarList </div>')
var compiled = $compile(html)
calendarHeaderRight.html(html)
compiled($scope)
View compilation in Angular basically traverses the entire DOM tree of whatever node you give it, creating a single function, that when called will execute every linking function from every directive it finds in that DOM tree, with the appropriate scope, element, attributes and (optionally) controllers.
Pretty much the same thing Tyler did just broken down.

Related

Get an element in DOM hierarchy from the link function of a directive [AngularJS]

I have a simple DOM hierarchy and I want to grab a specific set of elements (I want all the canvas elements). This is the entire template for this directive:
<div id='charts-container'>
<div class='chart-wrapper' ng-repeat='chart in getNumberOfCharts() track by $index'>
<canvas id="{{'exam-chart-' + $index}}" class='chart-canvas'></canvas>
</div>
</div>
I want to create a list with all the canvas within the #charts-container element, but I just can't. This is what I'm trying to do inside the link function:
link: function (scope, element, attributes, controller) {
var look = element.find('#chart-canvas');
$log.debug(look);
}
And then I get this element, but I don't know how to get all the chart-wrapper elements from here.
I tried doing look.context.children, it returned an empty list, but at the same time showed me what I wanted as if the list were populated, here is an image. If I try to access any index of this list, it returns undefined (which is fine, because it's an empty list. But why the console is showing me these values?)
What is the best way to achieve this? To get all the canvas elements in this template? (there are 15 of them). Thanks!
--- UPDATE ---
I realized that if I remove the ng-repeat attribute I'm using in the template, it works! But I need the ng-repeat...
element.find('.chart-canvas') manage to get the canvas element, but only if there are no ng-repeat attribute.
Is this a common issue when using ng-repeat. Is there any special treatment when falling in this case?
I found a solution in this thread.
Apparently I was trying to access DOM that hasn't been rendered yet. So, wrapping my query for the canvas with
$timeout(function() {
var canvasList = element.find('.chart-canvas');
}, 0);
solved the issue, since using $timeout will wait until all $digest cycles are complete.
I would like to get to know better how the rendering pipeline works in AngularJS, to avoid falling in issues of this kind. If anyone has a link to a thread or explanation of this, it would be much appreciated.
I think it should be element.find('.chart-canvas') instead of element.find('#chart-canvas'). Does it work with that change ?

Find related element using jQuery

Based on this DOM tree below when a comment reply button is clicked I need to use $(this) and then navigate to the next comment textarea .task-modal-cmt-reply-textarea
I am using jQuery and tried to use .parent().parent().closest('.task-modal-cmt-reply-textarea') and a few other combination without luck so far.
Can someone show me an efficient way to get this element into a var?
What I am trying to accomplish...
I have a click even on a comment reply button which insert a reply form into the DOM below a parent comment when the reply button is clicked using...
$document.on('click', '.cmt-reply-btn', function(e) {}
In this click event the reply form is put into the DOM with...
$parentCmtDomNode.after(cmtReplyFormTemplateHtml);
After the form is in the DOM I try to attach a jQuery plugin to it for #mention style capability using...
$('.task-modal-cmt-reply-textarea').mentionsInput({});
The problem
The #mention library works for the 1st clicked on comment form but all other reply forms do not work
another way to get a reference to that element, would be to do this:
var el = $(this).parent().parent().next().find('.task-modal-cmt-reply-textarea').eq(0);
note that the eq(0) just gives a single object back instead of an array with one element, which may or may not be necessary depending on what you want to do with it.
You need to do another .parent(), the two parent() you did only bring you up to the level of class "Activity-item Activity-comment" with data-activity-id = 12. Do another parent and you should be fine.
try this
var textarea_value=$(this).closest('.Activity-item').next('.Activity-item').find('form .task-model-cmt-reply-textarea').val();
or if its related with data-activityid = "12" so you can use
$(document).on('click','.cmt-reply-btn',function(){
var textarea_value = $(form[data-comment-parent-id = "'+$(this).attr('data-activityid')+' .task-modal-cmt-reply-textarea"]).val();
});
A more efficient way would be to use the parents api from jQuery then followed by your .closests
.parents('div')
The .parents() and .parent() methods are similar, except that the latter only travels a single level up the DOM tree. Also, $( "html" ).parent() method returns a set containing document whereas $( "html" ).parents() returns an empty set.
Then add the following sub selector to your closest chain.
.closest('textarea[name=^"task-modal-cmt-textarea"]')
This looks for the closest textarea with the name starting with task-modal-cmt-textarea. This is more efficient than what you have as this will eliminate any lookups on non textarea elements then it will only filter out the textareas that have that particular name.
EDIT: Updated Answer to the OP's recent edit.
$('.task-modal-cmt-reply-textarea').mentionsInput({});
This will select all of the ".task-modal-cmt-reply-textarea" that are on the screen at the time, it will not account for future ones. To achieve what you are looking for you should put a sub selector on this chain to allow it to attach to the newest form that was created.
$('.task-modal-cmt-reply-textarea',$($parentCmtDomNode).next('textarea')).mentionsInput({});
This should be placed after the
$parentCmtDomNode.after(cmtReplyFormTemplateHtml);
Try this:
var txt_html = $(this).parents('.Activity').children("textarea:first").html();
var txt_val = $(this).parents('.Activity').children("textarea:first").val();
In the parents() function you need to use the closest parent class/ id.
var el = $(this).parents('.Activity-item').next().find('.task-modal-cmt-reply-textarea').eq(0);

jQuery selection in polymer webcomponent

Well, out of the box, jQuery does not have support for selecting nodes inside webcomponent(s). (probably because document.querySelector() does not work for shadow DOM (nor it should, by definition)).
Our previous codebase was somewhat dependent on jQuery and many of the devs do not want to let go of the simplicity of $(...) selection. So, I wrapped up this quick and dirty trick.
window.$$ = function (that, selector) {
return $(that.shadowRoot.querySelectorAll(selector));
}
Usage (inside a lifetime callback or whenever the host node can be accessed):
jqel = $$(this, '.myClass'); // this has reference to the host
The question is, is there a better way to go about this?
i have created a jquery-polymer plugin that has a lot of functions that may help you dealing with polymer shadow dom
https://github.com/digital-flowers/jquery-polymer
to select any element inside a polymer element lets say
<my-button id='button1'></my-button>
first you need to get the button shadow root using
$("#button1").getShadowRoot()
or
$("#button1").shadow()
this will return the button shadow root as jquery object then you can select anything inside it for example
$("#button1").shadow().find("ul > li:first")
cheers ;)
As far as I know Jquery permits passing context as parameter JqueryContext, so the proper way would be:
$('selector',context)
As an example:
var component1 = document.querySelector('qr-code');
// Find some img inside qr-code component
var img1 = $('img',component1)

backbone not rendering the $el but can reference element directly

This is killing me, being reading the examples on this site but can't figure out why it works like this.
I want to pass back values to my view, which has buttons that you can use to change the values.
If I use the following
this.$el.empty().html(view.el)
View.el contains the correct html, but those not render on the screen. If I use the following
$("#handicap").html( view.el);
The values get displayed on screen but the events no longer get picked up eventhough if I put an onclick function in the html code it kicks off.
Ideally I would like to get this.$el.empty().html(view.el) working. It has to do with context but can't see why.
I have created a jsbin here http://jsbin.com/iritex/1/edit
If I have to use $("#handicap").html( view.el), do I need to do something special to unbind events. I have tried undelegate everything but that didn't do the trick either.
thanks
A Backbone View's el property will always contain a reference to a valid DOM object. However, that DOM object may or may not be in your display tree. It's up to you to make sure it's in the display tree when you need it to be. This functionality lets Backbone maintain the state of it's View element without it being rendered to the screen. You can add and remove a view from the screen efficiently, for example.
There are a few ways to get your View's element into the display tree.
1) Associate the view with an existing DOM element on the page by passing in a jquery selector to the initializer as the "el" property.
var view = new MyView({el: '#MyElementSelector'});
2) Associate the view with an existing DOM element on the page by hardcoding the jQuery selector it into the view's "el" property.
var MyView = Backbone.View.extend({
el: '#MyElementSelector'
});
3) Render it to the page from within another view
var view = new MyView();
view.render();
this.$el.empty().html(view.el);
If you're interested, I show examples in a Backbone Demo I put together.
You need to put both views into the DOM. Wherever you create the view that above is this needs to be inserted into the DOM. If you do that, then the first line will work fine this.$el.empty().html(view.el).

Multiple appendChild calls don't work

I read through several threads without find a clear answer.
I'm using a JavaScript library (Drinks.js) to put several widgets on my webpage.
The following code will add one single item to my div element pnlThermo:
function create(item) {
var thermo = Drinks.createElement('display');
thermo.setAttribute('id', item);
thermo.setAttribute('label', item);
Drinks.appendChild('pnlThermo', thermo);
}
Well, now I want to add several items to the same div element. No matter if I use a for cycle or call the function explicitly only the first item will be rendered. For example:
create('T1');
create('T2');
create('T3');
leads to show T1 only.
Perhaps I missed something, I'm quite new to JavaScript programming.
Thanks in advanced.
The reference manual ( http://goincompany.com/DTManual01.pdf ) says :
After you have created the HTML element, you have to append it to an
HTML container. In order to do this you have to use the appendChild
function, provided by the Drinks class. Drinks.appendChild('body',
gauge); 'body' is the id of the HTML container. If the parent is an
instrument, this function doesn't work. We have to use the appendChild
method of the instrument, but we'll see this later.
Seems to imply that the first parameter needs to be an HTML tagname, which makes little sense
but then the library is a little wierd IMHO.

Categories

Resources