ag-Grid adding css classes - javascript

I have this simple requirement for my Angular application...namely adding a css class when expanding or collapsing a row for the purpose of highlighting said row. I have tried using gridOptions.getRowClass as per the docs https://www.ag-grid.com/javascript-grid-row-styles/#gsc.tab=0 but that appears to have no effect.
My html I have added an event handler that will fire a method once the row expands/collapses. My html looks as follows:
<ag-grid-angular #agGrid style="width: 100%; height:85vh" class="ag-material grid-Holdings"
[gridOptions]="gridOptions"
[rowData]="rowData"
...
(rowGroupOpened)="addRowClass($event)">
</ag-grid-angular>
...and in my grid.component.ts I have the method which should add/remove a css class:
addRowClass(params) {
this.gridOptions.getRowClass = (params) => {
if (params.node.expanded) {
return 'my-css-class';
}
}
}
One interesting thing is that when I add break points in Chrome dev console I see that it never executes return 'my-css-class' but I cannot find any information in the official documentation as to why. I am really struggling with ag-Grid in general, and Angular integration with ag-Grid in particular. If this does not work is it better to just do this in vanilla JS somehow... If so, how might I go about this without ag-Grid api?

ag-grid already toggles some css classes for you: ag-row-group-expanded (when expanded) and ag-row-group-contracted (when not expanded). You should be able to accomplish your goal by applying the necessary styles to these classes.

Related

React jquery .toggleClass() does only work after compiler reloading

I´m trying to build this sideboard for my react application:
https://codepen.io/illnino/pen/nwPBrQ . Anyways, I ran into a problem and I´m not able to solve this on my own.
So what is my exact problem ?
This code does NOT work if I try to hover on the sideboard icon as it should. After refreshing the page manually, it doesnt work either. But I noticed, if my react compiler reloads this application (after any change in my file) and I DON'T refresh the page manually, it works.
So .toggleClass() does only work, after my compiler reloads the code. After reloading the page on my own, it doesnt work again.
My Code
My css code is exact the same as on codepen. Of course the javascript and the html code are in the same file. The html code is also the same, so I´ll only give you my JS code (In fact I´m using typescript, but that shouldn't matter):
React.useEffect(() => {
$(".gn-icon-menu").hover(function () {
let e = $(".gn-menu-wrapper")
e.toggleClass("gn-open-part")
});
$(".gn-menu-wrapper").hover(function () {
$(this).toggleClass("gn-open-all")
});
}, []);
What have I tried ?
I really dont know, what to try. I´ll hope somebody maybe has a clue, what the error could be...
JQuery manipulates the DOM, React schedules updates to its own Virtual DOM. You should try to avoid using both. They don't get along with one another. If you write all the styles in a css sheet and then use those, you can achieve the same results.
.gn-menu-wrapper {
/* Base Styles */
}
.gn-menu-wrapper:hover {
/* Hover Styles here */
}
Also double check your style sheets are SCSS and not CSS. In this codepen example they are using the format: (&) this will not work in CSS.
&::placeholder{
color: $f-c;
}

LitElement appending custom elements using button

I have a custom LitElement and inside it, I need to have a button that will dynamically append new custom elements (preferably using TemplateResult objects generated by html function) inside a container:
import { LitElement, html, render } from "lit";
import { customElement } from "lit/decorators.js";
#customElement('example-custom-component')
class CustomComponent extends LitElement {
render() {
return html`
<div id="custom-el-container">
</div>
<button #click=${this.appendNewCustomEl}>click me!</button>
`;
}
appendNewCustomEl() {
const templateToAppend = html`
<another-custom-component>
some other things added here
</another-custom-component>
`;
render(templateToAppend, this.shadowRoot?.querySelector('#custom-el-container'));
}
}
As you can see above I tried to achieve it by using the render function, but instead of appending it at the end of the container, I'm simply overwriting the content of the div. What am I doing wrong? What's the best approach to achieve those results? Please help.
EDIT:
New example for my question from comments about click events:
appendNewCustomEl() {
this.shadowRoot!.querySelector('#custom-el-container').insertAdjacentHTML("beforeend", `
<another-custom-component>
<button #click=${this.functionFromCustomComponent}>click me!</button>
</another-custom-component>
`)
}
If you really want to do it with lit-html and your container's content is purely what you are dynamically rendering on each button click, (i.e. not server side rendered content) or you are using lit-html v2 then you could have a list and track what you have rendered. something like:
items=[];
appendNewCustomEl() {
this.items.push(null);
const templatesToAppend = this.items.map(() => html`
<another-custom-component>
some other things added here
</another-custom-component>
`);
render(templatesToAppend, this.shadowRoot?.querySelector('#custom-el-container'));
}
in general what lit-html is good at and tries to achieve is an optimal re-render of markup when only parts are changed. not necessary a template engine alternative to handlebars, mustache and co.
In your example, you don't need it and could do it simply without lit-html:
appendNewCustomEl() {
this.shadowRoot!.querySelector('#custom-el-container').insertAdjacentHTML("beforeend", `
<another-custom-component>
some other things added here
</another-custom-component>
`)
}
I've slightly modified your example code to be more idiomatic Lit. Instead of using a querySelector and insertAdjacentHTML, it is preferred to render the array of templates declaratively. This has the added benefit that your functionFromCustomComponent event bindings "just work".
I've written the full example in a Lit playground.
The list of templates are stored in a reactive property, this.templates that schedules an efficient update whenever the list is updated.
Then the this.appendNewCustomEl method can push new templates to the list, and an automatic efficient render happens automatically.
this.templates is rendered into the #custom-el-container div using an expression:
<div id="custom-el-container">
${this.templates}
</div>
See Lit expressions documentation for other examples.
In my linked example, the list of templates turn blue when clicked to demonstrate the event working.
Not necessary but related, Lit.dev has a tutorial all about Working with lists that goes much more in depth if you're curious.

How to get <body> in React JS without DOM Manipulation

I'm rebuilding a project in React JS which i did in Vanilla JS, i came across to add, remove classes from <body> tag, i am also doing something when screen resizes.
I did this, this is a related piece of code, there's actually bunch of code:
...
document.body.onclick = (e) => {
const { lengua } = e.target.dataset
setLenguaOpen(lengua ? true : false) // if the target i or you clicked has data-lengua attr (a button has), a dropdown shows up
switchTheme // in another component i'm toggle 'switchTheme' (it is boolean), and here what i'm doing depending on it
? document.body.classList.add('dark-theme') // in my css, i'm changing values of variables i defined for colors and background-colors if body.dark-theme
: document.body.classList.remove('dark-theme')
}
window.addEventListener('resize', (e) => {
if (e.target.innerWidth >= 850) {
document.body.classList.remove('menu-open')
}
})
...
<FaBars onClick={() => document.body.classList.toggle('menu-open')}/> // a menu is located on 0 top: -60px when screen size < 850, i'm transforming body to y:60px to slide down the menu
It's working fine, but i think DOM Manipulation is preferably not used by most developers in React. I could do it differently to achieve what i wanted, but now i'm curios to learn how good React developers do what is done by DOM M..., especially the above example. If you have a better approach, i would love to hear it.
If you wanna see what exactly i'm talking, see that project: axelreid-store.netlify.app.
The code i shown is related to header section (languages dropdown, theme switcher, and menu toggle)
I'm sorry if this is a weird question!
Thanks!
Avoiding direct DOM manipulation when working with React is a good general principle, however there are quite a few cases when it is the best or only approach for solving a problem.
Accessing elements above the React application's top level element requires direct DOM manipulation. This also — definitely — is not going to clash with React's own DOM updating methods because they only affect elements inside the application.

Angular7 component view collapsing on data manipulation

I am experiencing the strangest issue. I do have a component that's style is controlled by some object it's handling. As the object is manipulated (by some inner component click), the whole view collapses to a height of 0.
I have tried to apply the view changes via ngStyle, ngClass, plain ol'javascript - but nothing ever worked. Second strange thing - handling outer component's component styles is perfectly working.
Object
const valueMap = {
width: '100%',
...
}
Pseudo Component Tree
<component-a>
<component-b [ngStyle]="{'width': valueMap.width} [valueMap]="valueMap">
<div (click)="changePosition()">Button</div>
</component-b>
</component-a>
Method
changePosition() {
this.valueMap.width = this.valueMap.width==='100%' ? '50%' : '100%';
}
I would really expect the component-b to collapse to a width of 50%, but not having the height collapse to zero. I can see in the code, that as I click the button the style is applied to the element - and if in Chrome DevTools I deactivate the applied style and activate it again, it is showing properly. Never had something like this. Can someone please help?
Thanks in advance. André
I tried to recreate your problem. altough i couldnt get the error you seem to be having, i think i can see the issue at hand:
from your html
<component-a>
<component-b [ngStyle]="{width: 'valueMap.width'} [valueMap]="valueMap">
<div (click)="changePosition()">Button</div>
</component-b>
</component-a>
i could get, that your "valueMap" is an Input() within component-b.
so i did that on my end aswell and declared valuemap on the outermost component (the one using component a and b)
i recreated your html and found parsing errors and whatnot until i realized something:
<app-collapse-on-click>
<app-collapse-child [ngStyle]="{'width': valueMap.width, 'background-color': 'rebeccapurple'}" [valueMap]="valueMap">
<div><button (click)="changePosition()">Button</button></div>
</app-collapse-child>
</app-collapse-on-click>
when using ngStyle, the style is interpreted as an object. meaning, in your case you need to remove the ' arround valueMap.width and add them to width.
i added the background color to get a visual result other than just the style html.
hope that somehow helps.
regards
Alan

Updating a simple jQuery / CSS code

I was hoping someone could help me out with this simple question: I’ve just started to learn jQuery and found a code to show hidden text after selecting an item.
I’d like to update it so that:
a.) The selected item is bold
b.) I can add placeholder text instead of starting off with a blank hidden text field
I foolishly assumed I could solve a.) by using the :active property in css, but that only works as long as the link is clicked on. (As soon as you release the mouse button it’s gone.) Just like b.), this is probably only possible by using jQuery as well? If so, would be really great if you could show me how to solve it. :)
The codes: http://jsfiddle.net/KUtY5/1/
JS
$(document).ready(function(){
$("#nav a").click(function(){
var id = $(this).attr('id');
id = id.split('_');
$("#menu_container div").hide();
$("#menu_container #menu_"+id[1]).show();
});
});
CSS
#menu_container {
width: 650px;
height: auto;
padding-left: 30px;
}
#menu_container div {
display:none;
}
HTML
<div id='nav'>
<a id="show_apps">Appetizers</a> | <a id="show_soups">Soups and Salads</a> | <a id="show_entrees">Entrees</a>
</div>
<div id="menu_container">
<div id="menu_apps">
Content of the App Section Here
</div>
<div id="menu_soups">
Content of the Soups Section Here
</div>
<div id="menu_entrees">
Content of the Entrees Section Here
</div>
</div>
Updated fiddle
You can realize a) using a custom class bold for example and the following code :
CSS
.bold{ font-weight: bold;}
JS
$(this).addClass('bold').siblings('a').removeClass('bold');
For b) I can't find any textfield in your code.
Hope this helps.
I have added some extra lines to your code and you can check it from here http://jsfiddle.net/KUtY5/483/.
You bold like this
$("#nav a").css("font-weight", 400); // First you make them thin
$(this).css("font-weight", 800); // Than you make them bold
You put placeholder like this
<div id="placeholder">
Placeholder
</div>
$("#placeholder").hide();
On the other hand I recommend you not to hide menu container. Rather hide the elements inside the menu_container. So you can put a plcaeholder in menu container and you can hide it.
To figure this out 2 questions must be asked / solved
how do you normally make text bold on a page... css right?
where do you want those styles to be defined? There are 2 places:
a. You can define it inside the javascript.
b. You can define it inside the projects css through normal methods (inline, external, embedded).
What's the difference? If you define it inside the javascript the code is self-contained. What i mean by that is you can copy/paste the JS code from one project to the next and you don't need to worry about copying related styles from the stylesheets or other sources because it's all in the JQuery that you've written.
In contrast if you define it outside the javascript in the regular places the code may not be self-contained however some find it easier to manage in the scope of that particular project because all your css is contained in one place (external stylesheet typically).
If you want to take option a, see the .css() method
If you want to take option b, see the style manipulation (toggle class in particular)
Note the examples in the above references should get you 90% of the way to understanding it.
Some final words. Learn Jquery, but i advise you to stay away from it as much as possible because it implements DOM thrashing instead of DOM caching (sizzle engine).
This video series will briefly go into why Jquery sucks for performance in the first video and the rest of the series is about how to create modular vanilla JS.
JQuery goes back and searches the DOM every time you need to make a change that is what
$.(*element*) is doing instead of just caching it.
The more nodes you have in the DOM the more processing power is used searching (because it has to go through the entire tree).
Then on top of that the more elements you have to make changes to (say if you use a css class selector) you have to add even more processing on top of that.
All this is fine if you're on a desktop, but what about a mobile platform? Where would you get all this processing power from?... It doesn't exist.

Categories