ExtJS: dynamically changing element styles - extjs

I'm trying to dynamically assign styles to my elements (in this case, a ExtJS displayfield).
I can't use CSS classes since I don't know what the colors will be until runtime.
I'm trying:
myDisplayField.getEl().applyStyles({ color: '#ff0000' }); //fail
myDisplayField.getEl().setStyle('color', '#ff0000'); //fail
Just to get the mechanism right, but neither seem to work.
It works using Ext.get(<div id>).setStyle(...), but that doesn't seem as clean to me. Is there a reason the former attempts don't work?
What am I missing?
Thanks.

The reason is simple: you're trying to set the styles on a wrong element. Each field, including displayfield, has quite complex table-based DOM structure that encapsulates the field label, the actual input element (or a div for display fields), and the supporting elements. field.getEl() returns the top, or main, element for a component; in this case that's the top <table> tag. What you need is the input element instead.
Now if you take a look at the DOM structure you'll notice that the <div> that you need to set styles on has an id of displayfield-123-inputEl. The -inputEl suffix is there for a reason; in most cases it indicates that the element has a Ext.dom.Element shortcut in its respective Component. For a field, that would be field.inputEl property that is available after the field has been rendered to the DOM. You can use that as well:
myDisplayField.inputEl.setStyle(...)
Or just use the convenience method available for the fields:
myDisplayField.setFieldStyle(...)
I would also suggest not hardcoding the colors but rather use CSS classes instead. In most cases there is a limited choice of colors depending on a condition, like invalid input, etc. Using CSS will require a bit more work upfront but will save you a lot of headache down the road, when someone will come up with a bright idea of changing the shade of red used for the invalid input, or somesuch.

Related

How do you determine which value className attribute takes in reactjs?

I know that we can use css classes for the className attribute but I see in a lot of tutorials that even if the value written for className is not used in the css file it is still used in the components. Can someone explain why? Or how to determine the value of the className we need to use?
The HTML class attribute (as set by the React className attribute) is a general way to label elements with some meaningful labels. It can be used for CSS styling, or JavaScript queries like document.querySelectorAll, or just to make the HTML intent more readable.
In particular, it's common to include classes in your HTML in case you'll need them later for CSS styling or JavaScript queries. To be clear, there's no list of valid class names; you can use whatever names you want, and use or not use them in order code as you wish.

How to get a the data-testid from a DOM component?

In my React project, sometimes a dynamically generated UUID needs to be added to the a data-testid value to ensure uniqueness amongst duplicate components in the DOM.
I have a test situation where I can grab the element I want. Now I want to get the dynamically generated data-testid from it. I've tried this but it doesn't work:
const questionDropdown = queryAllByText('Free Text')[0];
console.log(questionDropdown.getAttribute('data-testid'));
Any suggestions how to get it?
I think it's a dataset so you can get it like this:
console.log(questionDropdown.dataset.testid);
If you have an expected result you can test it with testing-library/jest-dom:
expect(questionDropdown).toHaveAttribute("data-testid", "test-id");
Doc: https://github.com/testing-library/jest-dom#tohaveattribute
I finally figured out how to do it!
So, I have a Semantic-UI Dropdown with a dynamically generated data-testid. The trick to getting the element is simply to use Regex, like this:
const questionTypeDropdown = getByTestId(/conditional-task-question-type/);
I'm revisiting this. I believe that the answer from adesuriey works great if you're dealing with conventional text, say in an Input element. But in the Semantic UI Dropdown it does not appear to work.
I think the problem lies with finding the correct ancestor element. I've tried many things but with no success.

CSS locator in Selenium for Python

CSS locator :".header-GlobalAccountFlyout-link.display-block" returns 3 elements in a class. I need to get to the last one -"Create an Account". Does anybody know how to finish writing CSS to get there? Thank You.
Using Attribute Selectors we don't necessarily need the Class selectors here at all.
You have a few options:
If data-uid never changes:
[data-uid="eRDhfBAS"]
If the href link never changes:
[href="/account/signup"]
If the alt text never changes:
[alt="Create an Account"]
If the data-tl-id never changes:
[data-tl-id="header-GlobalAccountFlyout-flyout-link-1"]
If there may be other elements with those same attributes and values, simply include your Class selectors as well. For example:
.header-GlobalAccountFlyout-link.display-block[href="/account/signup"]
Or you could combine some of the above attribute selectors...
[href="/account/signup"][alt="Create an Account"]

Set zIndex programmatically on a Div in AngularJS

I have a number of Div's on a layout, each of them draggable, so there's the possibility of the user dragging them into positions where they will overlap.
I want to set the most recently made visible div to have a z-index value that's +1 from the last, and for this I'm using a $scope.nextIndex variable that's incremented each time one of the div's is made visible.
Each div has its own variable to track its own z-index value: $scope.one_zIndex, $scope.two_zIndex, $scope.three_zIndex, and each correctly gets assigned an incrementally larger value as each div is shown, hidden and shown again.
Each div has its own class: one_z, two_z, three_z
What I can't make work is assigning the variable to the z-index style on the divs themselves via the controller.
var myVar = document.getElementsByClassName("one_z");
If I log this to the console, I get what I expect - an array with one element [0]
[]
0 : div#one_z
length : 1
one_z : div#one_z
__proto__ : HTMLCollection
I would assume that I could set the z-index simply like this:
myVar[0].style.zIndex = $scope.one_zIndex;
However this throws an error:
Uncaught TypeError: Cannot set property 'zIndex' of undefined
What am I missing? Or is there a better way to accomplish this?
Here is a working plunker https://plnkr.co/edit/aaDipIWdqpajghc2F2Da?p=preview
You can set zindex via ng-style:
<div ng-style="{'z-index': $lastIndex;}">...</div>
This example completely useless in your case, but there is an example of ng-style usage. In your case I'd set index as property of you div element data source.
What wound up working was this:
First, I switched to IDs instead of classes, which likely didn't impact the solution but as each div was only ever going to exist once, IDs was the more correct way of identifying them.
Then, in the function that displays the div, I used this:
_.defer(function(){
jQuery('#one_z').css('z-index', $scope.one_zIndex);
});
There appeared to be an issue where I was showing the div and trying to set its z-index before the DOM had updated to include the div, so _.defer (I'm using Underscore.js) prevented the accessing of the z-index until everything had updated once, and it works.
As I mentioned in another comment - using ng-style wasn't working for me, and I had tried the _.defer with that approach as well initially without success.
For the record - I've used jQuery() instead of $() so it's clear in the code that this is a jQuery and not an Angular solution, and while I'd ideally have liked a purely Angular solution to this problem, this is clean enough for me, and doesn't do any DOM manipulation outside of Angular's purview that impacts the rest of the application in any way, it's purely display candy.

Click element by Value - protractor

I am clicking to modal window which is pretty simple. In general only relevant part is this:
<div id="partSelection">
<button value="0" name="partSelection">BLATNÍK P L</button>
<button value="1" name="partSelection">BLATNÍK P P</button>
I need to click one of this button, I know how to click this with:
xpath:
element(by.xpath('//*[#id="partSelection"]/button[2]')).click();
also way with button text:
element(by.buttonText("BLATNÍK P P")).click();
but I noticed there as different values for each button and I belieave this is something which is not going to change by developers. Is there a way how to click element base on value?
Thank you for your advises.
Adding to an existing answer.
You can solve it using the following CSS selector:
element(by.css("#partSelection button[value=0]")).click();
Or, using a by.xpath() locator:
element(by.xpath("//div[#id='partSelection']/button[#value='0']")).click();
Note that, if you are going to use the "by value" technique often, to follow the DRY principle, it could be a good idea to define a custom by.value() locator:
How to globally add a custom locator to Protractor?
this example should work if you want to just look up a specific attribute. I usually refer to this css selectors when I'm trying to figure out the best way to find a specific attribute.
basically the breakdown is to find the tag you want in our case we want button and then we want to find the attribute within that tag. So we have the choice of value or name. Name is the same for both buttons so we don't want to use that. However the value is different for each button so that would be good to use in this case.
element(by.ccs('tag[attribute=""]');
tag = button
attribute = value
element(by.css('button[value="0"]')).click(); // button with text BLATNÍK P L
element(by.css('button[value="1"]')).click(); // button with text BLATNÍK P P

Resources