I need to get the style object for a row in ag-grid without using
document.querySelector(`[row-index="${rowIndex}"]`).style
Is there a way to get it from the RowNode or anything else?
Other than the code in your question. No you can't. If you look at the source code. They don't save any styles objects internally.
RowComp.prototype.postProcessStylesFromGridOptions = function () {
var rowStyles = this.processStylesFromGridOptions();
this.eAllRowContainers.forEach(function (row) {
return addStylesToElement(row, rowStyles);
});
};
And here is the definition of addStylesToElement(). As you can see the styles is applied directly to the DOM element.
export function addStylesToElement(eElement, styles) {
if (!styles) {
return;
}
Object.keys(styles).forEach(function (key) {
var keyCamelCase = hyphenToCamelCase(key);
if (keyCamelCase) {
eElement.style[keyCamelCase] = styles[key];
}
});
}
Related
I'm trying to create a function using vanilla JS that will:
Create a new DOM element
Assign it a Class Name
Place it in the DOM either appending to an existing div or inserting it specifically into the DOM if required using "insertBefore()"
I have come up with the somewhat inelegant solution below:
function createDomElem(elem, className, parent, refElement, type) {
var a = document.createElement(elem);
if (type == "append") {
document.querySelector(parent).appendChild(a);
} else if (type == "insert") {
document.querySelector(parent).parentNode.insertBefore(a, refElement)
}
a.className = className;
};
My problems with this solution are
Too many arguments to be passed
If not passing "insert" then you don't require refElement and to avoid "type" being mistaken for "refElement" you'd have to pass "refElement" as "null" and then define type as "append"
So my question is where can I streamline this function to become more useful within my program?
I'm also dreaming of the ability to be able to push child divs into the newly created div right within this function, defining how many child divs you would want and then using a for loop to append or insert these. Would this be better placed in a new function though?
I would split the code into two parts, as they have to separate concerns. I use something similar to the following for creating DOM elements:
var DomFactory = (function (document) {
var api = {
element: function (name, attributes) {
var el = document.createElement(name);
if (attributes) {
for (var key in attributes) {
if (attributes.hasOwnProperty(key)) {
el.setAttribute(key, attributes[key]);
}
}
}
return el;
},
div: function (attributes) {
return api.element('div', attributes);
}
};
return api;
}(window.document));
Usage:
var div = DomFactory.div({ 'class': 'hero' });
var table = DomFactory.element('table', { 'class': 'table table-bordered' });
Then for positioning, you could have a generalised position function:
function attach(source, target, position) {
switch (position) {
case 'before': {
target.parentNode.insertBefore(source, target);
break;
}
case 'after': {
if (target.nextSibling) {
target.parentNode.insertBefore(source, target.nextSibling);
} else {
target.parentNode.appendChild(source);
}
}
}
}
Usage:
attach(table, div, 'before');
Recently I was playing around with writing a small library for music theory in JS. One of the features I wanted to add was a jQuery style selector for creating/finding notes. For example:
Notes("a#") === Note {_note: 0, accidental: 1}
However, the structure of the library looked something akin to:
var Notes = function(sel) {
// initialisation stuff
var Note = function() {
// stuff for note objects
};
var scales = {
...
};
var selector(sel) {
// evaluate sel
return new Note(...);
};
if(sel !== undefined) {
return selector(sel);
}
return {
Note: Note,
scales: scales
};
};
module.exports = new Notes();
This way, I could use the library like this:
var Notes = require("Notes");
Notes.scales.major.c === [0,2,4,...];
But not like this:
var thisNote = Notes("A#");
As Notes was obviously an object that had been returned from the original Notes function. To use the selector function I'd have to expose it and then call it like this:
var thisNote = Notes.selector("A#");
But I want to mimic the jQuery/sizzle style (I had a bit of a search of jQuery's source, but couldn't find anything that helped).
How can I/should I have approached the design to allow for this kind of functionality? Would using prototypes instead of Closures been a more sensical approach? Or should I have aliased the library's name to another method to achieve the desired effect?
jQuery is like this:
function wrap() {
// do wrapping of DOM nodes
return {
value: function () { /*..*/ },
add_class: function () { /*..*/ }
};
}
wrap.extend = function () { /*..*/ }
wrap.ajax = function () { /*..*/ }
wrap("#abc"); // has `.value` and `.add_class)
wrap.ajax();
I am quite new to knockout.js, and I am enjoying learning how to make interfaces with it. But I have a bit of a wall while trying to make my interface more efficient. What I am trying to achieve is remove only the elements selected by $('.document_checkbox').serializeArray(), which contains the revision_id. I will then re-add the entries to the view model with a modified call to self.getDocument(), passing only the modified records which will be re-added. Can anyone help me how to remove the entries from the arrays based on the 'revision_id' values of $('.document_checkbox').serializeArray()
?
function Document(data) {
this.line_id = data.line_id
this.revision_id = ko.observable(data.revision_id);
this.status_id = ko.observable(data.status_id);
}
function DocumentViewModel() {
var self = this;
self.documents = ko.observableArray([]);
self.getDocument = function(){
//Reset arrays
self.documents.removeAll();
//Dynamically build section arrays
$.getJSON("/Documentation/Get-Section", function(allData) {
$.map(allData, function(item) {
var section = { name: item.array_name, display_name: item.display_name, documents: ko.observableArray([])};
self.documents.push(section);
})
//Add document objects to the arrays
$.getJSON("/Documentation/Get-Document", function(allData){
$.map(allData, function(item) {
var section = ko.utils.arrayFirst(self.documents(), function(documentSection) {
return documentSection.name === item.array_name;
});
section.documents.push(new Document(item));
});
});
});
}
self.updateStatusBatch = function(data,event){
$.post('/Documentation/Update-Status-Batch',
{
revision_id : $('.document_checkbox').serializeArray(),
status_id : event.currentTarget.value
}).done(
function(){
//This is where I get confused.
});
}
}
You should modify the /Documentation/Update-Status-Batch in order that it returns the deleted item id. So you will be able to remove it on the client side.
Try this "done" function:
function(removedItemId) {
self.documents.remove(function(doc){
return doc.status_id == removedItemId;
})
}
Take a look at the remove function.
I hope it helps.
I am working with a decent sized set of data relating to objects on the page and some objects need links applied to them onclick. The link to connect to is part of the dataset and I build a string for the link with the variable linkTarget and apply it like so.
if (dataTag[i][3]==true){
if(prepend==undefined || prepend=="undefined"){
var linkTarget=ResultsJSON["targetUrl"];
ele.onclick = function(){
window.open(linkTarget);
};
} else {
var linkTarget=prepend+ResultsJSON["targetUrl"];
ele.onclick = function(){
window.open(linkTarget);
};
}
ele refers to an element picked up with getElementByID. Now I am going through quite a few objects and the problem I have is the onclick for every object is the last value of linkTarget. This is all contained in a function and link target is a local variable so I have no idea why. I have tried using an array with something like
ele.onclick=function(){window.open(linkTarget[linkTarget.length-1]);};
and even
ele.onclick=function(){window.open(linkTarget.valueOf());};
with the same results. I am at a loss now and would appreciate any help.
Use Array.forEach() to iterate your data and watch your troubles melt away.
dataTag.forEach(function (item) {
if (item[3]==true) {
var linkTarget = "";
if (prepend==undefined || prepend=="undefined") {
linkTarget = prepend;
}
linkTarget += ResultsJSON.targetUrl;
ele.onclick = function () {
window.open(linkTarget);
};
}
});
See this compatibility note for using Array.forEach() in older browsers.
You're in a loop — therefore, you need to put your things-to-be-executed in another function, like so:
if(dataTag[i][3]) {
if(prepend) {
(function(linkTarget) {
ele.onclick = function() {
window.open(linkTarget);
};
})(ResultsJSON.targetUrl);
} else {
(function(linkTarget) {
ele.onclick = function() {
window.open(linkTarget);
};
})(ResultsJSON.targetUrl);
}
I also made some general corrections.
I'm using Slickgrid and I would like to change behavior of editor. Instead of copy&paste I tried to overload one of functions but it doesn't work. I cannot read loadValue function.
loadValue is defined as (some code omitted)
IntegerCellEditor : function(args) {
this.loadValue = function(item) {
defaultValue = item[args.column.field];
$input.val(defaultValue);
$input[0].defaultValue = defaultValue;
$input.select();
};
}
What I tried is:
function tristateIntegerCellEditor(check_field) {
var f = IntegerCellEditor;
var f_loadValue = f.loadValue;
f.loadValue = function(item) {
f_loadValue(item);
if (check_field) {
if (!item[check_field]) {
$select.disable();
}
}
};
return f;
}
Is there any way to substitute my function?
You need f_loadValue.call(this, item);
Otherwise the old loadValue get's called with it's context (this) as window (the default).
Related:
Adding hooks
_.wrap