JSS nested styles container

2019-07-28 21:14发布

I'm working with the React Material UI -> TextField component and I want to make some wrapper around it with the possibility to override the styles. According the documentation we have a 2 props to achieve this: 1) InputProps - Here we should pass classes into the inner Input component which is core of our TextField. 2) direct classes property which should be applied to the TextField directly. And that classes should contains rules for the FormControl

(sounds hard, actually it is when you are working with the Material UI =) )

anyway, I want to do something like this

import { withStyles } from 'material-ui/styles';

export const TextInputCSSCreator = theme => ({
    "FormControlClasses" : {
        "root" : { "color" : "red }
       }
    "InputClasses" : {
       "underline" : {
           "&:after" : {
               backgroundColor : "red",
           },
       }
    }

});

<TextField
                classses={this.props.classes.FormControlClasses}
                id={this.props.id}
                InputProps={{
                    classes : this.props.classes.InputClasses
                }}
                label={this.props.label}
                value={this.state.value}
                onChange={this._onValueChange}
                margin={this.props.margin}
            />

export default withStyles(TextInputCSSCreator)(TextInput);

Here I wanted to have a possibility to pass a whole object into my 2 targets. Input and FormControl. But here is the main issue and I don't know how to resolve it. It looks like JSS (it's the same withStyles from MaterialUi) doesn't work with the object which contains nested containers for the rules.

I've done this task via this ugly way. It looks like HELL but I didn't find any way how to avoid it. Could someone help me, please? Is it really only one way to accomplish this requirement?

Cause the way which I want to implement provide us flexibility, we might add any classes that we want at any time, when at the second way (below) we have to hardcode all possible classes at the start

Btw. I want to provide a mechanism to change the styles of my components from outer application so that's why I can't use CSS cause at the output it should be valid commonJS module.

export const TextInputCSSCreator = theme => ({
    "FormControlRoot" : {},
    "FormControlMarginNormal" : {},
    "FormControlMarginDense" : {},
    "FormControlFullWidth" : {},

    "InputRoot" : {},
    "InputFormControl" : {},
    "InputFocused" : {},
    "InputDisabled" : {},
    "InputUnderline" : {
        "&:after" : {
            backgroundColor : "red",
        },
    },
    "InputError" : {},
    "InputMultiline" : {},
    "InputFullWIdth" : {},
    "InputInput" : {},
    "InputInputMarginDense" : {},
    "InputInputDisabled" : {},
    "InputInputMultiline" : {},
    "InputInputType" : {},
    "InputInputTypeSearch" : {}
});

render() {
        const { classes } = this.props;
        return (

            <TextField
                classes={{
                    root : classes.FormControlRoot,
          marginNormal : classes.FormControlMarginNormal,
                    marginDense : classes.FormControlMarginDense,
                    fullWidth : classes.FormControlFullWidth,
                }}
                id={this.props.id}
                InputProps={{
                    classes : {
                        root : classes.InputRoot,
                        formControl : classes.InputFormControl,
                        focused : classes.InputFocused,
                        disabled : classes.InputDisabled,
                        underline : classes.InputUnderline,
                        error : classes.InputError,
                        multiline : classes.InputMultiline,
                        fullWidth : classes.InputFullWIdth,
                        input : classes.InputInput,
                        inputMarginDense : classes.InputInputMarginDense,
                        inputDisabled : classes.InputInputDisabled,
                        inputMultiline : classes.InputInputMultiline,
                        inputType : classes.InputInputType,
                        inputTypeSearch : classes.InputInputTypeSearch
                    }
                }}
                label={this.props.label}
                value={this.state.value}
                onChange={this._onValueChange}
                margin={this.props.margin}
            />


        );
    }

export default withStyles(TextInputCSSCreator)(TextInput);

1条回答
Emotional °昔
2楼-- · 2019-07-28 22:19

what I would do in this situation is to create theme for this component in separate file with createMuiTheme({}) and apply it to component with MuiTheme provider component. Exp:

import { createMuiTheme } from 'material-ui/styles';
const customTheme = createMuiTheme({
    overrides: {
        MuiInput: {
            root:{
                color: 'red',
            },
            underline: {
                    '&:after': {
                      backgroundColor: '#000000',
                    }
              },
        },
    }

});
export default customTheme;

and then use it on my component like this:

<MuiThemeProvider theme = {customTheme}>
[Your component]
</MuiThemeProvider>

Hope this helps!

查看更多
登录 后发表回答