Change TextField (MUI) background color when data present - material-ui

Using the 'styled' MUI component, with theme, a TextField component has been created.
When the TextField has no data (ie, empty), below styles were used to render the background as a custom-grey color:
'& .MuiInputBase-root': {
backgroundColor: theme.palette.background.grey01,
height: '40px'
},
This backgroundColor needs to change (to white) when data has been entered into the TextField. Not just 'on focus', but if data is present (ie, TextField is not-empty) the white-background must persist; however, if user deletes/removes data (ie, TextField is emptied by user), backgroundColor needs to go back to custom-grey.
From Chrome Inspect, was able to track down the relevant classes (including .Mui-focused):
MuiOutlinedInput-root MuiInputBase-root MuiInputBase-colorPrimary Mui-Focused MuiInputBase-formControl css-1byr8j2-MuiInputBase-root-MuiOutlinedInput-root
Have reviewed MUI documentation at https://mui.com/customization/how-to-customize/#use-rulename-to-reference-a-local-rule-within-the-same-style-sheet but unable to determine a way to know when value is populated / empty.

UPDATE:
I had overlooked the easiest and most elegant solution.
const StyledTextField = styled(TextField)`
.MuiInputBase-root {
background-color: ${({theme, value}) =>
!value && theme.palette.background.grey01};
}
`

Related

React-Bootstap-Typeahead: Manually set custom display value in onChange() upon menu selection

In the onChange of React-Bootstrap-Typeahead, I need to manually set a custom display value. My first thought was to use a ref and do something similar to the .clear() in this example.
But although .clear() works, inputNode.value = 'abc' does not work, and I'm left with the old selected value from the menu.
onChange={option => {
typeaheadRef.current.blur(); // This works
typeaheadRef.current.inputNode.value = 'abc'; // This does not work (old value is retained)
}}
I also tried directly accessing the DOM input element, whose ID I know, and doing
var inputElement = document.querySelector('input[id=myTypeahead]');
inputElement.value = 'abc';
But that didn't work either. For a brief second, right after my changed value = , I do see the new display label, but then it's quickly lost. I think the component saves or retains the menu-selected value.
Note: I cannot use selected, I use defaultSelected. I have some Formik-related behavior that I've introduced, and it didn't work with selected, so I'm stuck with defaultSelected.
The only workaround I found is to re-render the Typeahead component (hide and re-show, from a blank state) with a new defaultSelected="abc" which is a one-time Mount-time value specification for the control.
I couldn't get selected=.. to work, I have a wrapper around the component which makes it fit into Formik with custom onChange and onInputChange and selected wasn't working with that.
So the simple workaround that works is, if the visibility of the Typeahead depends on some condition (otherwise it won't be rendered), use that to momentarily hide and re-show the component (a brand new repaint) with a new defaultSelected, e.g.
/* Conditions controlling the visibility of the Typeahead */
!isEmptyObject(values) &&
(values.approverId === null || (values.approverId !== null && detailedApproverUserInfo)
)
&&
<AsyncTypehead defaultSelected={{...whatever is needed to build the string, or the literal string itself...}}
..
// Given the above visibility condition, we'll hide/re-show the component
// The below will first hide the control in React's renders
setFieldValue("approver", someId);
setDetailedUserInfo(null);
// The below will re-show the control in React's renders, after a small delay (a fetch)
setDetailedUserInfo(fetchDetailedUserInfo());

React-Bootstrap-Typeahead: Capture moment before setting selection into box (to allow conditional rejection)

In React-Boostrap-Typeahead, I need to capture the moment after the mouse has been clicked, but before the menu selection gets loaded into the Typeahead's box.
This is because I need to check items being selected, and for some of them, I need to display an alert with a Yes/No warning. Only if Yes is clicked can I proceed with setting that value into the box. Otherwise I need to reject the selection and keep it whatever it was prior to the mouse click.
I can't use onChange because by that point the selection is already in the box.
I can't use onInputChange because that is for typing rather than for menu selection. I need the post-menu-select, pre-box change.
If there are any workarounds please let me know.
You should be able to achieve what you're after using onChange:
const ref = useRef();
const [selected, setSelected] = useState([]);
return (
<Typeahead
id="example"
onChange={(selections) => {
if (!selections.length || window.confirm('Are you sure?')) {
return setSelected(selections);
}
ref.current.clear();
}}
options={options}
ref={ref}
selected={selected}
/>
);
Working example: https://codesandbox.io/s/objective-colden-w7ko9

Case Study for Card Development Using Pseudo-Classes

While developing a card, I used a pseudo-class for a component to implement a color changing effect. However, the color cannot be restored.
For example, the original background color of a picture was yellow.See Image
This figure shows the new background color after using the pseudo-class. It is red now.
See Image
In normal cases, the card’s background color is changed upon tapping, and will return to the original color when you lift your finger. So how to achieve this?
Simply add a tap event to the component using the pseudo-class. No logic processing is needed.
Sample code:
<div class="sitetype_box" widgetid="8e4bf1ca-f716-46f8-8614-16d1b35002c5" onclick="test">
</div>
CSS style:
.sitetype_box {
flex-direction: column;
background-color:#FFBF00;
padding: dpConvert(0) dpConvert($elementsMarginHorizontalL) dpConvert(0) dpConvert($elementsMarginHorizontalL);
}
/** Pseudo-class */
.sitetype_box :active{
background-color: #E40078;
}
Method:
test(){
console.log("message");
}
For Details,check Pseudo-classes for quick apps

How to set the visibility for row drag default icon in ag-grid angular 2+

In gridColumns i am setting the rowDrag: true. This creates a default icon for all the rows having children or single rows. But i wanted to have this icon only for particular rows by setting the visibility of a drag icon as hidden.
More over if i populate rowDrag true or false conditionally, then rows for which i dont want drag icon, icon won't come but its breaking the alignment. That's why i want something explicitly where i can set the rowDrag for all rows as true and then explicitly set the visibility as hidden.
Please help me in this case. not finding any solution.
If you just want to hide the drag icon you need to override the CSS. Just assign css class to the rows you want to hide and then in the CSS file make the visibility as hidden.
Assign class as below
this.rowClassRules = {
"hide-row-drag-class": function(params) {
if (params.node.rowIndex % 2 == 0) {
return true;
}
}
};
Override CSS file
.yourTheme .yourClass .ag-row-drag{
visibility: hidden;
}
The above code assigns a CSS class to all odd rows and then will hide the row drag icon based on the CSS
https://plnkr.co/edit/dIfq96KHFmEx25BnC5ze?p=preview

Dashing: Changing text color based on input to List widget

I am fairly new to HTML/CSS so this may be a newbie question.
I have a list widget that I am using to show the name of nodes (:label) from an API and the last time those nodes reported (:value). If the node has reported within the last hour I want the text color to be green, if it hasn't I want it to be red (pretty simple logic).
I have been trying to use :status-warning and :status-danger to do this, but these options do not change each value independently, rather it changes the whole widget's text color.
This is my coffeescript code, which I got from https://github.com/Shopify/dashing/issues/24 :
ready: ->
if #get('unordered')
$(#node).find('ol').remove()
else
$(#node).find('ul').remove()
onData: (data) ->
#clear existing "status-*" classes
$(#get('node')).attr 'class', (i,c) ->
c=c.replace /\bstatus-\S+/g, ''
# add new class
$(#get('node')).addClass "status-#{x.status}"
Do I need to create a custom widget for this, or is there a built in mechanism to change the text color of values?
I wouldn't bother changing the coffeescript. It's not necessary.
Not sure if you are still looking for an answer for this, but I managed to work something out for this recently. If you set up your code in the .rb file that sends data to your list so that it does some checking for whether the value was updated or not, and then determines and adds a 'color' attribute to the set of data that is sent, you can then tell your list to use that 'color' value to specify which CSS class to look at. The CSS class can then be set up with whatever colors fits the 'color' attribute.
My dashboard (.erb) code for the list is the same, so that doesn't need to change.
In the job file:
myList.rb
# get your label and value for the list before here.
if myValue >= 75.00
myColor = "green"
elsif myValue <= 74.99
myColor = "red"
else
myColor = "white"
end
results.push({:label => myLabel, :value => myValue, :color => myColor})
send_event("myList", items: results)
so from the above we can see that a color variable is sent with the label and value. Now we just need to make the list.html and the list.scss recognise it.
here's the changes in my list.html Only 4 lines should change to look like the 2 below (in the ordered list (<ol></ol>), and unordered list(<ul></ul>):
list.html
<span class="label"><div data-bind-class="item.color" data-bind="item.label"></div></span>
<span class="value"><div data-bind-class="item.color" data-bind="item.value"></div></span>
The data-bind-class is binding the class to whatever is in item.color (which i know in my example will be: red, green, or white)
Then we just need to tell the list.scss how to handle these classes by adding this to the bottom of the file:
list.scss
.white {
color: white;
}
.red {
color: #B31D2B;
}
.green {
color: green;
}
Note: CSS can handle plain English colors. You mentioned you were new to css so I guess it's worth clarifying. I've used a mixture of plain English colors: 'white', and 'green' and a hex code color: '#B31D2B'. This hex code is a darker red which I found was a bit easier on the eyes.
You could use this method to do anything with the text just thinking about it now. It doesn't need to be 'color' specifically. So you could change color to 'state' and have a 'good' state passed through as item.state and then have a 'good' class in your scss that changes the font style, font size, color, font weight. Whatever you'd like really :)