Attaching rowSelect event on dynamically created DHTMLX Grid - javascript

I am working with DHTMLX Grid and I am constructing multiple grid objects using a method like
JS:
function renderGrid(render_area, dataURL, skin, loop_index) {
var scope = this;
var grid_obj = loop_index + '_grid';
grid_obj = new dhtmlXGridObject($(render_area).attr('id'));
grid_obj.selMultiRows = true;
grid_obj.imgURL = "codebase/imgs/";
grid_obj.init();
grid_obj.setSkin(skin);
grid_obj.load(dataURL);
}
I am doing this using a jquery plugin.Now I want to attach 'RowSelect' event to all these dynamically created grids.
I thought of doing it using the grid object on HTML page and attaching the event there like this
0_grid.attachEvent("onRowSelect",scope.clickEvent);
but unfortunately I am unable to get these dynamically created grid objects on the HTML Page(0_grid is undefined on the HTML Page).
Glad if somebody can suggest me some good solution

You can use jquery's .on method to attach the events to dynamically created elements. You would need to attach the event to a static element that is a parent of your grid elements.
parent.on("event", "selector", "data", handler());

You have 2 options, either attach the listener within renderGrid or outside of it. I removed the loop_index parameter as you don't need it:
Within:
function renderGrid(render_area, dataURL, skin) {
var grid_obj = new dhtmlXGridObject($(render_area).attr('id'));
grid_obj.selMultiRows = true;
grid_obj.imgURL = 'codebase/imgs/';
grid_obj.init();
grid_obj.setSkin(skin);
grid_obj.load(dataURL);
grid.attachEvent('onRowSelect', function () {
// Or instead of an anonymous function you could use this.clickEvent
});
}
Outside (you need to return the grid object from renderGrid:
function renderGrid(render_area, dataURL, skin) {
var grid_obj = new dhtmlXGridObject($(render_area).attr('id'));
grid_obj.selMultiRows = true;
grid_obj.imgURL = 'codebase/imgs/';
grid_obj.init();
grid_obj.setSkin(skin);
grid_obj.load(dataURL);
return grid_obj;
}
var grid = renderGrid($('#grid'), '/data.xml', 'dhx_skyblue');
grid.attachEvent('onRowSelect', function () {
// Or instead of an anonymous function you could use this.clickEvent
});
If you want to attach the event listener inside of a loop I would recommend reading this paragraph from JavaScript Garden first.

Related

How to add an event listener to dynamically generated content using Renderer2?

I am trying to add a click event listener to a div that is dynamically generated after page load but I can't seem to get the event to register. I am following the instructions found in this answer however, it is not working for me.
In my ngOnInit() I have a combineLatest():
combineLatest([this.params$, this.user$]).subscribe(([params, user]: [Params, User]) => {
this.artistId = parseInt(params['artist']);
this.user = user;
if (this.artistId) {
this.artistProfileGQL.watch({
id: this.artistId
}).valueChanges.subscribe((response: ApolloQueryResult<ArtistProfileQuery>) => {
this.artist = response.data.artist;
this.initElements(); // WHERE I CALL TO INITIALIZE DYNAMIC DOM ELEMENTS
});
})
In this block, I call initElements() which is where I create certain DOM elements. I've included most of them below. Essentially, I have a header element, and inside this header element, I create a followBtn, that looks like this (i removed the title, followers, elements etc from the code for brevity). I added comments in caps for the most relevant lines:
initElements() {
const parentElement = this.el.nativeElement;
this.header = parentElement.querySelector('ion-header');
// Create image overlay
this.imageOverlay = this.renderer.createElement('div');
this.renderer.addClass(this.imageOverlay, 'image-overlay');
this.colorOverlay = this.renderer.createElement('div');
this.renderer.addClass(this.colorOverlay, 'color-overlay');
this.colorOverlay.appendChild(this.imageOverlay);
this.header.appendChild(this.colorOverlay);
var artistHeader = this.renderer.createElement('div');
this.renderer.addClass(artistHeader, 'artist-header');
// HERES WHERE I CREATE MY BUTTON ELEMENT
this.followBtn = this.renderer.createElement('div');
this.renderer.addClass(this.followBtn, "follow-btn");
var followText = this.renderer.createText('FOLLOW');
this.renderer.appendChild(this.followBtn, followText);
this.renderer.appendChild(artistHeader, this.followBtn);
this.renderer.appendChild(this.imageOverlay, artistHeader);
// HERES WHERE I CREATE MY LISTENER
this.followButtonListener = this.renderer.listen(this.followBtn, 'click', (event) => {
console.log(event);
});
}
However, when I click on the element, I don't get anything printed to my console. If I change the target of the listener to a DOM element, the click listener works. What am I doing wrong?

What is correct way to pass on event parameter in DOJO?

I am working on Dojo Version 1.8.I have designed one custom widget as below. Its a snippet
<div>
<div>
<input
id ="NZ1",
data-dojo-attch-point = "NZ1"
data-dojo-attch-type = "ecm.widget.ValidationTextBox"
data-dojo-attch-event = "onBlur : makeAllSmall"
/>
</div>
<div>
<input
id ="NZ2",
data-dojo-attch-point = "NZ2"
data-dojo-attch-type = "ecm.widget.ValidationTextBox"
data-dojo-attch-event = "onBlur: makeAllSmall"
/>
</div>
</div>
Here is event handler
makeAllSmall : function(evt){
var currVal=evt.target.value;
currVal = currVal.toLowerCase();
/**Some Other business logic on currVal **/
}
This evt is always coming as undefined . I am quite new to Dojo. Am I missing something in HTML side ? I tried to change HTML as below but not luck
<input
id ="NZ2",
data-dojo-attch-point = "NZ2"
data-dojo-attch-type = "ecm.widget.ValidationTextBox"
data-dojo-attch-event = "onBlur : makeAllSmall"
data-dojo-args="e"
/>
First thing first, is there a typo in the method "onBlurr"? I see there is an extra 'r'. Shouldn't it be "onBlur"?
If you look at the DOJO API documentation for onBlur event, it doesn't pass an event object like what you are expecting
onBlur()
Defined by: dijit/_FocusMixin
Called when the widget stops being "active" because focus moved to something outside of it, or the user clicked somewhere outside of it, or the widget was hidden.
Examples
Example 1
var btn = new Button();
// when /my/topic is published, this button changes its label to
// be the parameter of the topic.
btn.subscribe("/my/topic", function(v){
this.set("label", v);
});
Next, in your event handler, you are trying to change the text to lowerCase and this can be done like
makeAllSmall : function(){
var currVal=this.get("value");
currVal = currVal.toLowerCase();
/**Some Other business logic on currVal **/
}
Another way of doing this without the event handler is to force the ValidationTextBox to convert everything to lowercase using construction parameters like
<input
id ="NZ2",
data-dojo-attach-point = "NZ2"
data-dojo-attach-type = "ecm.widget.ValidationTextBox"
data-dojo-props='lowercase:true'
data-dojo-attach-event = "onBlurr : makeAllSmall"
/>
Note that I have added data-dojo-props='lowercase:true'
Hope this helps.
You should be able to attach a DOM event to your custom widget by:
Using data attribute data-dojo-attach-event in the markup.
And using _AttachMixin passing your callBack function.
Example:
<div id="somenode"><span data-dojo-attach-point="anattachpoint"
data-dojo-attach-event="click: clicked">Click me</span></div>
var MyDijit = declare([ _WidgetBase, _AttachMixin ], {
// .. declaration goes here ..
clicked: function(e) {
// handle event
}
});
// instantiate the dijit instance, which will attach to the 'somenode' div.
var mydijit = new MyDijit({}, dom.byId('somenode'));
mydijit.startup();

SAPUI5 TreeTable's getRows method returns empty array on the first call

I am trying to build an SAPUI5 application using TreeTable and I'm facing some problems to use its methods.
In my app, I have a button which triggers this method.
onChangeViewContext: function(oEvent) {
.........
.........
var aViewContext = oContext.oModel.getProperty(sPath + "/ViewContext");
var aDataModel = oContext.oModel.getProperty("/ApplicationCollection/" + sAppId + "/DataModel");
var oStructure = this._createParentChildStructure(aDataModel);
var oTreeModel = this.getView().getModel("treeModel");
oTreeModel.setData(oStructure);
this._oViewDetailLine = oSource.getParent().getParent().getParent();
this._oViewDetailLine.setVisible(false);
this.byId("idSelectElementsPanel").setVisible(true);
this._setSelectedItems(aViewContext, oTree);
}
What I'm trying to do here is only bind the rows with my treeModel, get tree table object and send it to my _setSelectedItems method which below.
_setSelectedItems: function(aViewContext, oTree) {
oTree.clearSelection();
var sElementName;
var aSelectedIndices = [];
var aElements = [];
var aRows = oTree.getRows();
aRows.forEach(function(row) {
if (row._oNodeState !== undefined) {
aElements.push(row.getCells()[0].getText());
}
});
I need to get rows array here because I will use it for setting selected items of tree table. The problem is when "onChangeViewContext" triggered, oTable.getRows() returns an empty array. But when I click cancel button (which just hides my tree table, nothing more) and then trigger "onChangeViewContext" function again, I can get the rows array completely.
Even on the first call when I try to get table's model, I can get the treeModel and its data correctly.
I've tried to refresh bindings, aggregations etc. But no luck.
By the way, I'm using row binding in my xml view like this :
<t:TreeTable id="idSelectElementsTree" rows="{path: 'treeModel>/'}" selectionMode="MultiToggle" enableSelectAll="false"
rowSelectionChange="onSelectElement">
I'm really drowning here so any any help would be appreciated.
Edit : rest of the setSelectedIndexes function :
aViewContext.forEach(function(name) {
sElementName = name;
if (aElements.indexOf(sElementName) !== -1) {
aSelectedIndices.push(aElements.indexOf(sElementName));
}
});
aSelectedIndices.forEach(function(idx) {
if (oTree.getRows()[idx]._bHasChildren) {
oTree.expand(idx);
}
oTree.addSelectionInterval(idx, idx);
});
What could help here is to add an event rowsUpdated="onRowsUpdated" to the table in the XML view. This event is triggered after the table has been loaded and will hence provide you with the data via;
this.getView().byId("sTableId").getRows();
The difference to your approach is that the event would not be triggered by the press of a button but automatically, as the table is rendered. You can then also use this function to trigger another one as per your use case.

How to reset an elements class to it's initial value

How can I reset an elements 'class' attribute to it's initial value?
I am building a tooltip popup which starts with class="ttPopup". This is then set to the appropriate orientation by adding classes such as class="ttPopup top left".
Problem is when the Popup windows closes, how do I reset the class to it's original value ready for the next time?
There are several ways you could do it:
store in a custom attribute
store in a javascript array
store in localStorage
etc.
Not completely sure if I am correct to use a custom property on the element or not but here is the solution I have used at the moment:
eTooltip.addEventListener("mouseenter", function (oEvent) { ttOpen(oEvent); } );
eTooltip.addEventListener("mouseleave", function (oEvent) { ttClose(oEvent); } );
function ttOpen(oEvent) {
var thisPopup = oEvent.target.getElementsByClassName("ttPopup")[0];
thisPopup.origClassName = thisPopup.className;
}
function ttClose(oEvent) {
var thisPopup = oEvent.target.getElementsByClassName("ttPopup")[0];
if (thisPopup.origClassName) { thisPopup.className = thisPopup.origClassName; thisPopup.origClassName = null; }
console.log(thisPopup.className)
}
Thanks for your help.

changing backbone views

I have a question about the way backbone handles it views.
Suppose I have the following code:
<div id="container">
<div id="header">
</div>
</div>
After this I change header into a backbone view.
How can I now remove that view from the header div again after I'm done with the view and add ANOTHER view to the same div?
I tried just overwriting the variable the view was stored in. This results in the view being changed to the new one...but it will have all the event handlers of the old one still attached to it.
Thanks in advance!
http://documentcloud.github.com/backbone/#View-setElement
This won't automatically remove the original div - you'll want to do that yourself somehow, but then by using setElement you'll have the view's element set to whatever you passed it.. and all of the events will be attached as appropriate. Then you'll need to append that element wherever it is that it needs to go.
--- Let's try this again ----
So, first thing to keep in mind is that views reference DOM elements.. they aren't super tightly bound. So, you can work directly with the jquery object under $el.
var containerView = new ContainerView();
var headerView = new HeaderView();
var anotherHeaderView = new AnotherHeaderView();
containerView.$el.append(headerView.$el);
containerView.$el.append(anotherHeaderView.$el);
anotherHeaderView.$el.detach();
containerView.$el.prepend(anotherHeaderView.$el);
Or you can create methods to control this for you.
var ContainerView = Backbone.View.extend({
addView: function (view) {
var el = view;
if(el.$el) { //so you can pass in both dom and backbone views
el = el.$el;
}
this.$el.append(el);
}
});
Maybe setting the views by view order?
var ContainerView = Backbone.View.extend({
initialize: function () {
this.types = {};
},
addView: function (view, type) {
var el = view;
if(el.$el) { //so you can pass in both dom and backbone views
el = el.$el;
}
this.types[type] = el;
this.resetViews();
},
removeView: function (type) {
delete this.types[type];
this.resetViews();
},
resetViews: function () {
this.$el.children().detach();
_.each(['main_header', 'sub_header', 'sub_sub_header'], function (typekey) {
if(this.types[typekey]) {
this.$el.append(this.types[typekey]);
}
}, this);
}
});

Categories