AntD: Config Provider API for customization does not allow text customization - themes

I am using AntD Config Provider to provide custom styles to certain AntD components. Been playing with the button component and it seems there is only certain things you can change. I seem unable to change the text color of the button. Has anyone figured out how to do this?
These are the attributes I have tried to change for text color with no success.
Updates:
The button is of Primary type and the Token attribute is not part of the individual component so it can not be used.
Here is what the code looks like
export const SecondaryConfigProvider = (props:any) => {
return (
<ConfigProvider
theme={{
components: {
Button: {
colorText: "orange",
colorPrimaryBg: "red",
colorPrimaryBorder: "red",
colorPrimaryBorderHover: "red",
colorPrimaryHover: "lightgray",
colorPrimary: "blue",
colorPrimaryActive: "lightgray",
colorPrimaryTextHover: "lightgray",
colorPrimaryText: "lightgray",
colorPrimaryTextActive: "lightgray",
colorBgContainer: "blue",
colorBorderBg: "red",
controlOutline: "none"
}
}
}}
>
{props.children}
</ConfigProvider>
)
}
the button layout is here
import {Button, DatePicker} from 'antd'
import { PrimaryConfigProvider } from "./PrimaryConfigProvider"
import { SecondaryConfigProvider } from "./SecondaryConfigProvider"
export const TestingConfig = () => {
return (
<>
<PrimaryConfigProvider>
<Button type="primary">Primary Button</Button>
</PrimaryConfigProvider>
<SecondaryConfigProvider>
<Button type="primary">Secondary Button</Button>
</SecondaryConfigProvider>
</>
)
}
App.jsx -- contains <TestingConfig/>
Index.js
const root = ReactDOM.createRoot(
document.getElementById('root') as HTMLElement
);
root.render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>
);

If you will go to definition of some Button's token (right click on token then go to definition, or hover token and press F12, or ctrl+click) - you'll be able to see the whole list of them.
Button: {
//others token: value ...
colorPrimary: 'red',
},
If it doesn't help you can I see how do you use <Button /> in your code? As I can see your screenshot your tokens are defined for primary button, so you need to pass props to your button component as below:
<Button type="primary"> I am a button <Button />

Related

v-navigation-drawer controlled state from a sub-component

I have a v-navigation-drawer which can be opened by clicking a button in a sub component.
So I changed v-model="drawer" to simply value="drawer" otherwise I get a warning about mutating a prop which makes sense (feels like doing some dirty angular double-way data binding ^^).
Here's the code:
layouts/default.vue:
<template>
<Header :toggleLeftMenu="toggleLeftMenu" />
<LeftMenu :show="showLeftMenu" :toggleLeftMenu="toggleLeftMenu" />
</template>
<script>
export default {
data() {
return {
showLeftMenu: true,
}
},
methods: {
toggleLeftMenu() {
this.showLeftMenu = !this.showLeftMenu;
},
}
}
</script>
components/layout/LeftMenu.vue:
<v-navigation-drawer
:value="show"
width="300"
clipped
fixed
app
>
This issue is that the drawer can be closed by clicking on the backdrop (on small devices). I need to plug the backdrop click to toggleLeftMenu prop, but according to the doc, this doesn't seem to be possible.
How can I achieve full control on the component? Is this #backdropClick event missing or something?
I tried to use #input but it creates an infinite loop which also makes sense.
Thanks
Using vuetify 2.6.1.
I changed v-model="drawer" to simply value="drawer" otherwise I get a warning about mutating a prop
This is not quite the right decision. Of course you should not use drawer as model, but you can create an internalDrawer prop in LeftMenu component, and leave the v-model where it is.
One of the possible ways to resolve your issue is to emit events from both sub-components into its parent.
So let's rewrite your LeftMenu component this way:
<template>
<v-navigation-drawer v-model="internalShow" width="200" clipped fixed app>
some drawer data
</v-navigation-drawer>
</template>
<script>
export default {
props: {
show: Boolean,
},
data() {
return {
internalShow: this.show,
};
},
watch: {
show (val) {
this.internalShow = val;
},
internalShow (val) {
if (val !== this.show) {
this.$emit("change-drawer-state");
}
},
},
};
</script>
In this case, every time when the internalShow state changes, an change-drawer-state event will be emitted.
Your Header component can be rewrited the same way:
<template>
<v-btn #click="$emit('change-drawer-state')">Drawer button</v-btn>
</template>
And this is the code of your parent component:
<template>
<div>
<Header #change-drawer-state="toggleLeftMenu" />
<LeftMenu :show="showLeftMenu" #change-drawer-state="toggleLeftMenu" />
</div>
</template>
<script>
import LeftMenu from "./LeftMenu";
import Header from "./Header";
export default {
components: {
LeftMenu,
Header,
},
data() {
return {
showLeftMenu: false,
};
},
methods: {
toggleLeftMenu() {
this.showLeftMenu = !this.showLeftMenu;
},
},
};
</script>
Both change-drawer-state event handlers are calling the same method - toggleLeftMenu and then the method changes show prop of navigation-drawer.
You can test this solution in a CodeSandbox playground.

Nativescript Vue ListPicker does not update it's items

I am trying to load topics (just string values) from a backend and display them in the ListPicker. However the ListPicker won't update it's items which should be displayed.
The code is as follows:
<template>
<Page>
<ActionBar title="Create Challenge" icon="">
<NavigationButton text="Back" android.systemIcon="ic_menu_back" #tap="goBack" />
</ActionBar>
<StackLayout>
<Label text="TOPIC" class="fab lblSubTitle"/>
<ListPicker :items="topics" v-model="selectedItem" />
<Button text="check" #tap="checkIt" />
</StackLayout>
</Page>
</template>
<script>
import {ObservableArray} from 'tns-core-modules/data/observable-array';
import {FirebaseService} from '../../services/firebase-service';
export default {
data() {
return {
selectedItem: 0,
topics: new ObservableArray(["some", "hardcoded", "items"])
};
},
methods: {
goBack() {
this.$navigateBack();
},
checkIt() {
this.topics.push("new item");
}
},
created() {
console.log("Create Challenge - Loading Topics")
// Fetch additional items from the Firebase DB
FirebaseService.fetchTopics().then(result => {
result.forEach(topic => {
this.topics.push(topic);
});
});
}
}
</script>
<style scoped>
.lblSubTitle {
font-size: 15;
margin: 10dp;
color: red;
}
</style>
So the FirebaseService.fetchTopics() returns an array of strings. This works perfektly fine and adds the received values to the ObserveableArray topics.
However the ListPicker only shows the hardcoded values. Not the dynamically added ones. Also the checkIt() method won't update the view.
I have tried to change topics to a conventional array with no effect.
Link to the Playground
NativeScript Version: 6.5.0
Android Device: Pixel 2 - Android 9
ListPicker doesn't listen to changes on ObservableArray. You must use a simple Array and mutate the changes
this.topics = [...this.topics, "new item"];

Vuetify Snackbar leave event

I manage to implement a global Vuetify Snackbar.
My problem is to detect when the snackbar close. I read that this component support Vue transition event since 1.2. But it work only on the enter event not the leave ones.
here a fiddle for comprehension.
<transition #before-enter="beforeEnter" #before-leave="beforeLeave" #after-enter="afterEnter" #after-leave="afterLeave" #leave="leave">
<v-snackbar v-model="snackbar" top right>
Hello
<v-btn #click="snackbar = false" dark>Close</v-btn>
</v-snackbar>
</transition>
I faced the same problem and solved this way:
export default {
data: () => ({
errorMessage: '',
snackTimeout: 6000,
}),
watch: {
errorMessage() {
setTimeout(() => {
this.clearErrorMessage();
}, this.snackTimeout);
},
},
methods: {
setErrorMessage(message) {
this.snackMessage = message;
},
clearErrorMessage() {
this.snackMessage = '';
},
},
};
<template>
<v-snackbar
:value="errorMessage"
:timeout="snackTimeout"
top
>
{{ errorMessage }}
<v-btn
color="error"
flat
#click.stop="clearErrorMessage"
>
{{ 'close' }}
</v-btn>
</v-snackbar>
</template>
Define an attribute with the timeout and another with the message to show by the snackBar.
Define a function to set the message and another to clear it.
Define a watch for the message text and set a timer with the same timeout of the snackBar to clear it.
The snackBar appears only when the message is not empty.
You can use get and set methods to handle reading and updating the bound model separately.
I made a generic snackbar component that can be triggered from any other component. I'm using Vuex, vue-property-decorator and typescript here, so adjust accordingly.
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.js"></script>
<template>
<v-snackbar v-model="snackbar" max-width="100%">
<template v-slot:action="{ attrs }">
{{ text }}
<v-btn color="primary" text fab v-bind="attrs">
<v-icon dark #click="close()"> mdi-close-circle-outline </v-icon>
</v-btn>
</template>
</v-snackbar>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator'
#Component({})
export default class Snackbar extends Vue {
get snackbar() {
return this.$store.state.snackbar.show
}
set snackbar(show: boolean) {
this.$store.dispatch('updateSnackbar', { show, text: '' })
}
get text() {
return this.$store.state.snackbar.text
}
public close() {
this.$store.dispatch('updateSnackbar', { show: false, text: '' })
}
}
</script>

How do I add checkboxes to admin-on-rest admin on rest create form and post the checkbox value to backend

I have added the material-ui/Checkbox component in admin-on-rest create form with source attribute. But after I click save button, I could not see the checkbox value in posted data.
But I can see 'title' and 'body' fields value in posted data. Can someone please tell, Why this code is not working?
Here is my sample code:
export const PostCreate = (props) => (
<Create {...props} >
<SimpleForm>
<TextInput source="title" />
<LongTextInput source="body" />
<Checkbox
label="Label on the left"
labelPosition="left"
source="test"
value="yes"
/>
</SimpleForm></Create>
);
Sure Checkbox is not a react-on-admin component. Please use BooleanInput
The BooleanInput.js module from rect-admin, Switch is replaced with Checkbox:
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import FormControlLabel from '#material-ui/core/FormControlLabel'
import FormGroup from '#material-ui/core/FormGroup'
import Checkbox from '#material-ui/core/Checkbox'
import { addField, FieldTitle } from 'ra-core'
const sanitizeRestProps = ({
alwaysOn,
basePath,
component,
defaultValue,
formClassName,
initializeForm,
input,
isRequired,
label,
locale,
meta,
options,
optionText,
optionValue,
record,
resource,
allowEmpty,
source,
textAlign,
translate,
translateChoice,
...rest
}) => rest
export class CheckboxInput extends Component {
handleChange = (event, value) => {
this.props.input.onChange(value)
}
render() {
const {
className,
input,
isRequired,
label,
source,
resource,
options,
...rest
} = this.props
return (
<FormGroup className={className} {...sanitizeRestProps(rest)}>
<FormControlLabel
control={
<Checkbox
color="primary"
checked={!!input.value}
onChange={this.handleChange}
{...options}
/>
}
label={
<FieldTitle
label={label}
source={source}
resource={resource}
isRequired={isRequired}
/>
}
/>
</FormGroup>
)
}
}
CheckboxInput.propTypes = {
className: PropTypes.string,
input: PropTypes.object,
isRequired: PropTypes.bool,
label: PropTypes.string,
resource: PropTypes.string,
source: PropTypes.string,
options: PropTypes.object,
}
CheckboxInput.defaultProps = {
options: {},
}
export default addField(CheckboxInput)

Admin on rest custom button

I would like to make a custom button that would be used to fetch. I want the button to be usable like this:
export const LogList = (props) => (
<List {...props} perPage={100} title="Logs and Reports" filters={< FileFilter/>}>
<Datagrid>
<TextField source="inputfile" label="Input File" />
<TextField source="cycle" label="Cycle" />
<TextField source="job" label="Job" />
<TextField source="name" label="File Name" />
<ShowButton/>
<JobCancel/>
</Datagrid>
</List>
);
Where is my button is <JobCancel/> up above (similar to how ShowButton is implemented). I want the button to fetch(controller_service/archivedfiles/${id}, { method: 'DELETE', body:{} }); on click.
Is something like this possible?
P.S. I am new to Admin on rest
You can also find an example for custom actions in the demo repository for reviews (accept, reject): https://github.com/marmelab/admin-on-rest-demo/tree/master/src/reviews
Misread your question. So am editing my answer.
I have custom button for my list view.
It's a straightforward Redux connected component.
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import RaisedButton from 'material-ui/RaisedButton';
import { editorAssign as editorAssignAction} from '../customActions/EditorAssignActions'
import styles from '../styles/styles'
class EditorAssignButton extends Component {
constructor(props){
super(props);
this.state = { disabled: false };
}
handleClick = () => {
const { editorAssign, record } = this.props
editorAssign(record.id) //call the action
this.setState({
disabled: true
})
}
render() {
const editorAssignStyle = styles.editorAssignStyle;
return (<RaisedButton label='Add To Edit'
onClick={this.handleClick}
disabled={ this.state.disabled }
primary={true}
/>)
}
}
EditorAssignButton.propTypes = {
editorAssign: PropTypes.func,
record: PropTypes.object
}
export default connect(null, {
editorAssign: editorAssignAction
})(EditorAssignButton)
AOR has documentation on how to write custom actions and trigger side effects with Sagas.
https://marmelab.com/admin-on-rest/Actions.html
DELETE is an action available with AOR Rest so your requirement should be quite standard.
Here is the EditorAssign view. It is a straightforward list and datagrid component
import React from 'react';
import { ReferenceField,
ChipField,
SelectInput,
ReferenceInput,
TextField,
List,
Filter,
Datagrid} from 'admin-on-rest';
import AssignTaleEditToSelf from '../buttons/AssignTaleEditToSelf'
const EditorAssignView = (props) => {
return (
<List {...props} title="Fresh Tales" perPage={20} sort={{ field: 'id', order: 'ASC' }} filter={{"status": "NEW"}} filters={ <EditorFilter /> } >
<Datagrid >
<TextField source="id" label="id" style={{ textAlign: 'center'}} />
<TextField source="taleTitle" label="Title" />
<TextField source="taleText" label="Content" style={{maxWidth: '150px'}} />
<ReferenceField label="Writer" source="writer_id" reference="appUsers">
<ChipField source="name" />
</ReferenceField>
<AssignTaleEditToSelf label="Assign To Self" />
</CustomDatagrid>
</List>
)
}
}

Resources