Typescript wrong type with Material-UI Higher Order Components - node.js

I'm trying to update from Material-UI 1.x to Material-UI 3.9.2.
I had a few components, including the example below, that were working properly with Higher Order Components (HOC), but I have a hard time at migrating them to 3.9.2.
In this example, I reduced a problem and don't get why the typings are wrong (Typescript 3.3.3). It seems to me to be consistent with the way MUI PropInjector works.
Here is an example:
import { createStyles, Theme, withStyles, WithStyles } from '#material-ui/core';
import Dialog, { DialogProps } from '#material-ui/core/Dialog';
const styles = (theme: Theme) => createStyles({
defaultPaperWidthSm: {
backgroundColor: "#fafafa",
minWidth: 320,
maxWidth: 700
},
largePaperWidthSm: {
backgroundColor: "#fafafa",
width: 700,
maxWidth: 700,
[theme.breakpoints.up('md')]: {
minWidth: 900,
width: "unset",
maxWidth: "80vw",
}
}
})
export default withStyles(styles)(
function ResponsiveDialog(props: DialogProps & WithStyles<typeof styles>) {
let { classes, className, ...otherProps } = props
return <Dialog {...otherProps} />
}
)
Using it as a component:
<ResponsiveDialog open={true}>
<span>Blabla</span>
</ResponsiveDialog>
It returns this error, and I don't get why:
Type '{ children: Element; open: boolean; }' is not assignable to type 'IntrinsicAttributes & Pick & StyledComponentProps<"defaultPaperWidthSm" | "largePaperWidthSm"> & { children?: ReactNode; }'.
Property 'open' does not exist on type 'IntrinsicAttributes & Pick & StyledComponentProps<"defaultPaperWidthSm" | "largePaperWidthSm"> & { children?: ReactNode; }'.

Found it!
It's working if I use an arrow function:
export default withStyles(styles)(
(props: DialogProps & WithStyles<typeof styles>) => {
let { classes, className, ...otherProps } = props
return <Dialog {...otherProps} />
}
)
There are still issues when I combine multiple HOC, I have the feeling MUI typings are currently a bit broken. But it's another problem.

Related

Type '{ children: never[]; title: string; content: Element; }' is not assignable to type 'IntrinsicAttributes & { title: any; }'

I am working on react website in typescript. I am using polaris wizard component, for that I have made on custom component called in which want to pass two arguments. but when I am calling that component in wizard.tsx , I am getting below error in .tsx file where I am using that component (i.e wizard.tsx).
Type '{ children: never[]; title: string; content: Element; }' is not assignable to type 'IntrinsicAttributes & { title: any; }'.
Property 'children' does not exist on type 'IntrinsicAttributes & { title: any; }'.
//wizard.tsx (file in which <CustomContainer> has been called.)
<CustomContainer
title = {"Organization information"}
content= {
<div>
Name of organisation
</div>
</div>
}
>
</CustomContainer>
//Wizard.tsx
const CustomContainer = ({title}:{title:any}, {content}:{content:any}) => {
return (
<Container
header={
<Header
variant="h2"
>
{title}
</Header>
}
>
{content}
</Container>
);
}
export default CustomContainer;
Any suggestions what I am missing?
This is not how attributes should be passed. It should work if you change customContainer to this.
const CustomContainer = ({ content, title }: { content: any; title: any }) => {
return <div id={title}>{content}</div>;
};

How to change sort icon in detailslist

I am using detailslist, is there a quick property to change sort icon?
I find below styles but do not know how to set it
That's not possible because sort icon is implemented directly inside DetailsColumn.base.tsx:
{column.isSorted && (
<IconComponent
className={classNames.sortIcon}
iconName={column.isSortedDescending ? 'SortDown' : 'SortUp'}
/>
)}
But if you really need that functionality you can recompose DetailsList Component. Hint:
<DetailsList
onRenderDetailsHeader={(headerProps, defaultRender) => {
return headerProps && defaultRender ? (
{defaultRender({
...headerProps,
onRenderColumnHeaderTooltip: props => {
return <TooltipHost {...props} children={/* Implementation here! */} />
}
})}
) : null;
}}
/>
Keep the same children functionality and rewrite icon render.
Codepen example for hint.
You are able to achieve what you want by doing some css trickery. In my use-case I only had to change the color. In the example below I added a background-image for setting your own icon.
<DetailsList onRenderDetailsHeader={(headerProps, defaultRender) => {
return defaultRender({
...headerProps,
styles: {
root: {
selectors: {
'.ms-DetailsHeader-cell': {
backgroundColor: '#0f238c',
color: 'white'
},
'.ms-Icon': {
color: '#0f238c',
backgroundColor: '#0f238c',
backgroundImage: decendingFilter ? 'url([PATHTOIMG1])' : 'url([PATHTOIMG2])',
backgroundRepeat: 'no-repeat',
backgroundSize: 'contain',
},
},
}
}
});
}}
/>

How to pass svg component as props in next js

import styled from "styled-components";
import { SmallImg } from "./Icon";
import InfoSvg from "../assets/info.svg";
export interface InfoT {
text: string;
}
const Info = ({ text }: { text: string }) => {
const [showInfo, setShowInfo] = useState(false);
return (
<Wrapper>
<SmallImg
url={InfoSvg}
color="#2d50f9"
clickable={true}
/>
<InfoSvg />
</Wrapper>
);
};
Simply the InfoSvg component below comes out well but when
It doesn't work when I pass the component as props.
In react.js this is working well but in Next.js not working...
In browser console tab error message is InfoSvg is not a styled component and cannot be referred to via component selector. See https://www.styled-components.com/docs/advanced#referring-to-other-components for more details.
So I look that link, but i can't solve this problem. And SmallImg Component is
export const SmallImg = styled("span")<ImgPropsT>`
width: ${(props) => (props.width ? props.width : 12)}px;
height: ${(props) => (props.height ? props.height : 12)}px;
-webkit-mask: url(${(props) => props.url}) no-repeat 50% 50%;
background-color: ${(props) => (props.color ? props.color : "#222222")};
`;

How to return back to previous screen from React StackNavigator to specific Tab

I am using React StackNavigator which has structure like this:
-----BottomNavigator
-------TabNavigator (has 3 screens)
---------StackNavigator
so I want to return to previous screen from stackNavigator to TabNavigator (screen 2).
Here is my code for TabNavigator:
const ServiceTabNavigator = createMaterialTopTabNavigator(
{
screenone: screenone,
screentwo: screentwo,
screenthree: screenthree
},
{
tabBarOptions: {
activeTintColor: "#1B5357",
inactiveTintColor: "gray",
style: {
backgroundColor: "#fff",
color: "#1B5357"
},
indicatorStyle: {
backgroundColor: "#1e90ff"
}
},
navigationOptions: {
tabBarLabel: "ESTH",
tabBarIcon: ({ tintColor }) => (
<Icon name="bars" color={tintColor} size={24} />
)
}
}
);
Here is for the StackNavigator which has code like this but it does not go to the screen2 instead screen1 of tabNavigator.
static navigationOptions = ({ navigation }) => ({
title: "Request Service",
headerLeft: (
<TouchableOpacity
onPress={() => {
() =>
navigation.dispatch(
NavigationActions.reset({
index: 0,
actions: [
NavigationActions.navigate({ routeName: "MainNavigator" }) //MainNavigator is bottomNavigator
]
})
);
navigation.navigate("screentwo");
}}
>
<Icon
name="times"
type="font-awesome"
iconStyle={{ color: "#000" }}
containerStyle={{ marginLeft: 16 }}
/>
</TouchableOpacity>
),
headerTitleStyle: {
color:'#00CA9D',
fontWeight: 'bold',
},
headerStyle: { borderBottomWidth:0 }
});
Thank you
I use react-navigator.. there is a property named jumpToIndex for this.
I solved it this way for my needs to open a Modal instead jumping to the given Tab.
Maybe you can modify to fit your needs:
<TabBarBottom
{...props}
jumpToIndex={(index) => {
if (index === 5) {
// This is the MORE-Tab-Button. Don't switch to tab, but open the Modal
props.navigation.navigate('Menu_Screen');
} else {
jumpToIndex(index);
}
}}
/>
From how you described your navigation hierarchy it looks like your root navigator is always Main/BottomNavigator, so why do you call dispatch reset before navigating to screentwo?
Seems like the issue might be that the reset action is not finished before you try to navigate to screentwo, so you end up on initialRoute of MainNavigator.
So calling just navigation.navigate("screentwo") (without reseting root) should do what you want to achieve.
In case you really need to reset the root, try executing the navigation to screentwo using dispatch as well, to make sure the actions are performed in sequence
const navigateAction = NavigationActions.navigate({
routeName: route,
params: params
})
navigation.dispatch(navigateAction)
OK after digging up I have found out the way
React NavigationV2 Way:
navigation.navigate('MainNavigator', {}, NavigationActions.navigate({ routeName: 'Requests' }))
React NavigationV3 Way:
navigation.navigate(NavigationActions.navigate({
routeName: 'MainNavigator',
action: NavigationActions.navigate({ routeName: 'Requests' })
}))
BottomNavigator as MainNavigator
Screentwo as Requests
In a nutshell navigation.navigate() has third parameter which acts likes second navigation.
So It first Navigate to MainNavigator ------then----> Screen2 in TabNavigator
Thanks to David check this post. Hope it will help someone else in future.
How to navigate between different nested stacks in react navigation

Getting Kendo UI, DataViz Map, & Angular 2 To Work Together

I'm using Kendo UI & Angular 2 in a project, but cannot for the life of me seem to get the map widget to work with shapefiles in Angular 2.
It looks like I have to integrate with jQuery since the map component is not listed as an Angular 2 component yet. So, I've followed the instructions outlined here. However, it still doesn't seem to work. Here's what I currently have:
exampe.module.ts
...
import "#progress/kendo-ui";
...
example-map.html
<div #kendoMap style="height: 1000px;">
</div>
example-map.component.ts:
import { AfterViewInit, Component, ElementRef, OnDestroy, ViewChild } from '#angular/core';
declare var kendo: any;
#Component({
selector: 'example-map',
templateUrl: './example-map.html'
})
export class ExampleComponent implements AfterViewInit, OnDestroy {
#ViewChild('kendoMap')
kendoMap: ElementRef;
constructor () { }
ngAfterViewInit() {
const element = kendo.jQuery(this.kendoMap.nativeElement);
// This line throws an error
element.kendoMap({
controls: {
attribution: false,
navigator: false,
zoom: false
},
zoom: 7,
center: [32.7767, 96.7970],
layers: [
{
type: 'tile',
zIndex: -1,
urlTemplate: "https://#= subdomain #.tile.openstreetmap.org/#= zoom #/#= x #/#= y #.png"
},
{
type: 'shape',
style: { fill: { opacity: 0.7 } }
// shapefile layer data will be added here later by ajax
}
],
markers: []
});
}
ngOnDestroy() { kendo.destroy(this.kendoMap.nativeElement); }
}
This was throwing an error:
TypeError: Function has non-object prototype 'undefined' in instanceof check.
To fix that, I included the version of jQuery they were using in my index.html file:
<script src="http://code.jquery.com/jquery-3.3.1.slim.min.js"
integrity="sha256-3edrmyuQ0w65f8gfBsqowzjJe2iM6n0nKciPUp8y+7E=" crossorigin="anonymous"></script>
But now it's barfing about access 'width' off of something undefined.
ExampleComponent.html ERROR TypeError: Cannot read property 'width' of undefined
at init.translate (http://localhost:3000/vendor.bundle.js:89908:98)
at init.translate (http://localhost:3000/vendor.bundle.js:262525:25)
at init._translateSurface (http://localhost:3000/vendor.bundle.js:224872:31)
at init._reset (http://localhost:3000/vendor.bundle.js:224758:19)
at init.proxy (http://localhost:3000/vendor.bundle.js:52589:13)
at init.trigger (http://localhost:3000/vendor.bundle.js:4780:34)
at init.window.kendo.window.kendo.devtools.kendo.ui.Widget.trigger (eval at _translateSurface (http://localhost:3000/vendor.bundle.js:224869:27), <anonymous>:587:33)
at init._reset (http://localhost:3000/vendor.bundle.js:337450:19)
Has anyone hit this before or know a great tutorial to use Kendo Maps w/ Angular 2+ ?
The issue with this was the order in which the component was rendering versus what was in the DOM. Moving the initialization into a jQuery block resolved the issue, like so:
ngAfterViewInit() {
kendo.jQuery(() => {
const element = kendo.jQuery(this.kendoMap.nativeElement);
...
});
}

Resources