Material-ui LeftNav with Toolbar not working - meteor

Following is my code for implementing LeftNav with Toolbar. I am using Material-UI package for meteor. LeftNav does not show up at all. When similar configuration used with AppBar it works fine. Need some help to fix the problem.
var {Toolbar, ToolbarGroup, , ToolbarTitle, FontIcon,FlatButton,ToolbarSeparator,IconButton,LeftNav,FlatButton} = MUI;
let {SvgIcons} = MUI.Libs;
let LeftIcon = <SvgIcons.NavigationExpandMore />
let LeftIcon = <SvgIcons.NavigationExpandMore />
var menuItems = [
{ route: 'get-started', text: 'Get Started' },
{ route: 'customization', text: 'Customization' },
{ route: 'components', text: 'Components' },
{ type: MenuItem.Types.SUBHEADER, text: 'Resources' },
{
type: MenuItem.Types.LINK,
payload: 'https://github.com/callemall/material-ui',
text: 'GitHub'
},
{
text: 'Disabled',
disabled: true
},
{
type: MenuItem.Types.LINK,
payload: 'https://www.google.com',
text: 'Disabled Link',
disabled: true
}
];
injectTapEventPlugin();
Header = React.createClass({
_toggle(e){
e.preventDefault()
this.refs.leftNav.toggle()
},
render(){
return(
<div>
<LeftNav ref="leftNav" docked={false} menuItems={menuItems onLeftIconButtonTouchTap={this._toggle}} />
<Toolbar>
<ToolbarGroup key={0} float="left">
<ToolbarTitle text="React" />
</ToolbarGroup>
<ToolbarGroup key={1} float="right">
<FontIcon className="muidocs-icon-custom-sort" />
<FlatButton label="Questions" linkButton={true} href="/login" secondary={true}/>}
<ToolbarSeparator/>
{Meteor.userId() ? <FlatButton label="Logout" onClick={Meteor.logout}/> : <FlatButton label="Login" linkButton={true} href="/login" primary={true}/>}
</ToolbarGroup>
</Toolbar>
</div>
)
}
});

I'm just looking at this now too. It maybe that these are deprecated items?
https://github.com/callemall/material-ui/issues/2491
however, this is using 0.14 - not sure which version you're on
update: I have a working example and code here:
https://github.com/dcsan/react-hot/blob/master/app/client/layouts/MainLayout.jsx#L25-L53
demo
http://react-hot.meteor.com
hope that helps!

Related

Render nested items based on an API response using materialsUI

im trying to make a nested side menu using nexJS and materialsUI dinamically based on an API response that would look like this:
const Response1 = [
{
id: 1,
name: "Logistics",
icon: "warehouse",
url: "/",
children: [
{
id: 2,
name: "Express",
icon: "precision_manufacturing",
url: "/",
children: [
{
id: 3,
name: "request",
icon: "list_alt",
url: "/Logistica/Express-Cedis",
children: [],
},
],
},
{
id: 5,
name: "Dashboards",
icon: "bar_chart",
url: "/Logistica/Dashboard",
children: [],
},
],
}
]
I was able to iterate the object and get all the items and display them, the only problem is that the ones that are childs should be visible only when clicking the parent, and i only have them all in a list statically, i did this with a code like this:
const mapStructure = (nodes: any) => {
if (nodes) {
return nodes.map((node) => (
<>
<ListItemButton onClick={handleClick}>
<ListItemIcon>
<Icon>{node.icon}</Icon>
</ListItemIcon>
<ListItemText primary={node.name} />
{open ? <ExpandLess /> : <ExpandMore />}
</ListItemButton>
{mapStructure(node.children)}
</>
));
}
};
the idea is that the parent objects display just as the code above, but the children elements display in a collapse like the one below:
<Collapse in={open} timeout="auto" unmountOnExit>
<List component="div" disablePadding>
<ListItemButton sx={{ pl: 4 }}>
<ListItemIcon>
<Icon>{node.icon}</Icon>
</ListItemIcon>
<ListItemText primary={node.name} />
</ListItemButton>
</List>
</Collapse>
i tried something like "if node has a child, render like the first example, and when it doesn´t have childs render like the second examle" but i can´t manage to write it correctly

Fluent/Fabric change dropdown menu css

I have a dropdown from Fluent UI and want to change the CSS of the dropdown options.
I can add classes though className to the dropdown, but I can't reach the dropdown options through adding CSS here because the dropdown options exist on a layout on the same level as <div id="root">. Is there a way I can set the CSS only to apply to this dropdown (preferably from the dropdown component)?
My code is as following:
const styles = mergeStyleSets({
main: {
selectors: {
"& .ms-Dropdown-title": {
color: "red"
},
"& .ms-Dropdown-optionText": {
color: "blue" //does not work
}
}
}
});
const Test = () => {
const options = [
{ key: "A", text: "I am an option" },
{ key: "B", text: "Do not choose me" },
{ key: "C", text: "Here is a third option" }
];
return (
<div style={{ width: "300px" }}>
<Dropdown
placeholder="Select an option"
label="Choose something"
options={options}
className={styles.main}
/>
</div>
);
};
Codesandbox:
https://codesandbox.io/s/bold-moon-u0ol2?file=/src/App.js
Just use the styles property:
<Dropdown
placeholder="Select an option"
label="Choose something"
options={options}
styles={{
title: { color: 'red' },
dropdownOptionText: { color: 'blue' }
}}
/>
It gives fine grained control over the single elements of a dropdown that can be styled and, in an editor like VSCode, autocompletion suggests all styleable elements.
Updated Codesandbox: https://codesandbox.io/s/elegant-noyce-ddjek?file=/src/App.js
If you want to use a conditional styling for each dropdown option based on the disabled property, you can do the following:
export const optionsWithCustomStyling: any = (
options: IDropdownOption[]
) =>
options.map((x) => ({
key: x.key,
text: x.text,
styles: {
optionText: {
color: `${x.disabled ? '#FF0000' : '#000000'}`,
},
}
})
)

Alignment Issue with tabBarLabel and Icon in react-navigation-material-bottom-tabs

I am using createMaterialBottomTabNavigator from React Navigation for one of my project. If i use tabBarIcon and tabBarLabel together icon is overlapping with text. Need help to fix the issue.
Here's what i tried -
const MainNavigator = createMaterialBottomTabNavigator({
Offers: {
screen: OffersNavigator,
navigationOptions:{
tabBarIcon: (
{focused}) => {
return <IconButton icon="tag" style={{marginBottom: 5}} color={focused ? '#2E98FF' : '#000'} size={20}/>
},
tabBarLabel: 'Offers',
},
},
Search: SearchNavigator,
Settings: SettingsNavigator,
});
Margin Icon like this. It will work perfectly.
<IconButton icon="tag" style={{marginTop: -3}} color={focused ? '#2E98FF' : '#000'} size={20}/>

Wordpress Gutenberg autocomplete - saving attributes

I want to develop a custom block that will let the user pick some information from autocomplete. I manage to create the autocomplete component on edit function.
A user can select an item but i don't know how to handle the attribute save.
I'm trying to save the selected item as attribute package_name. I created the onChange function on Autocomplete component but event.target.value is undefined.
Here is my code from block.js
const { __ } = wp.i18n; // Import __() from wp.i18n
const { AlignmentToolbar,
BlockControls,
registerBlockType } = wp.blocks;
const { RichText } = wp.editor;
const { Autocomplete, } =wp.components;
const MyAutocomplete = () => {
const autocompleters = [
{
name: 'fruit',
triggerPrefix: '#',
options: [
{ name: 'Apple', id: 1 },
{ name: 'Orange', id: 2 },
{ name: 'Grapes', id: 3 },
{ name: 'test', id: 4 },
],
getOptionLabel: option => (
<span>
{ option.name }
</span>
),
getOptionKeywords: option => [ option.name ],
isOptionDisabled: option => option.name === 'Grapes',
getOptionCompletion: option => (
<abbr title={ option.name }>{ option.name }</abbr>
),
}
];
function onChangeAuto(newContent){
console.log('autocompletexx '+newContent);
}
function onSelectAuto(event){
console.log(event.target);
console.log( event.target.value);
}
return (
<div>
<Autocomplete completers={ autocompleters }>
{ ( { isExpanded, listBoxId, activeId } ) => (
<div
contentEditable
suppressContentEditableWarning
aria-autocomplete="list"
aria-expanded={ isExpanded }
aria-owns={ listBoxId }
aria-activedescendant={ activeId }
onChange={onChangeAuto }
onSelect={onSelectAuto}
>
</div>
) }
</Autocomplete>
<p class="autocomplete_p">Type # for triggering the autocomplete.</p>
</div>
);
};
registerBlockType( 'residence-gutenberg-block/membership-package-settings', {
title: __( 'Residence - Membership Package Settings' ), // Block title.
icon: 'shield',
category: 'common',
keywords: [
__( 'membership-package-settings' ),
],
attributes:{
package_id:{
type:'string',
select:'p'
},
package_name:{
type:'string',
},
},
edit: function( props ) {
const { attributes: {package_name}, className,setAttributes,isSelected } = props;
return (
<div className={ props.className }>
<form>
<label className="wpresidence_editor_label">Current Package: {package_name}</label>
<MyAutocomplete></MyAutocomplete>
</form>
</div>
);
},
save: function( props ) {
// Rendering in PHP
return null;
},
} );
Passing down onChange, onSelect to the div element won't work, because these attributes are only applicable to the form field elements (as input, select, etc.).
I checked the documentation and the source code and didn't find any details or official approaches for dealing with the case.
However, I'm seeing two possible approaches for getting the selected value:
1. Using Autocomplete onReplace prop
Looking into the Autocomplete's source code, I noticed that onSelect callback invokes onReplace prop with the selected option as array. It may not fit all the cases, but you can give it a try! It may be enough for your case! You can try to add your handler to the onReplace as follows:
<Autocomplete
onReplace={ option => { console.log(option) } }
completers={ autocompleters }>
{ ( { isExpanded, listBoxId, activeId } ) => (
<div
contentEditable
suppressContentEditableWarning
aria-autocomplete="list"
aria-expanded={ isExpanded }
aria-owns={ listBoxId }
aria-activedescendant={ activeId }
/>
) }
</Autocomplete>
2. Listen for <div /> changes manually
You can add onInput, onBlur listeners to the <div />, having an uncontrolled react div component and when the div's value is changed then we can keep the changed value in your parent component's state.
Here's a great discussion, which describes these technique: React.js: onChange event for contentEditable
The good think is that there's already a plugin (based on this discussion) that can do it for you: react-contenteditable.
Firstly you have to convert your <MyAutocomplete /> component to be a statefull (not functional) and then:
import ContentEditable from 'react-contenteditable'
// Boilerplate ...
<Autocomplete completers={ autocompleters }>
{ ( { isExpanded, listBoxId, activeId } ) => (
<ContentEditable
html={this.state.html}
onChange={this.handleChange}
contentEditable
suppressContentEditableWarning
aria-autocomplete="list"
aria-expanded={ isExpanded }
aria-owns={ listBoxId }
aria-activedescendant={ activeId }
/>
) }
</Autocomplete>
Conclusion
I'm surprised that in the Autocomplete's documentation there aren't any details for this case. I guess it's because of the following statement (27.08.2018):
Gutenberg is being developed on GitHub, and you can try an early beta
version today from the plugin repository. Though keep in mind it’s not
fully functional, feature complete, or production ready.
However, one of both mentioned approaches above will help you, until they provide a complete API to work with their components.
I would suggest you to keep wrapping the Wordpress's <Autocomplete /> with your own component - in order to easily refactor your code later, when they release the complete API.
If you have questions, feel free to comment below.

Magnific-popup gallery duplicate images when i use it with Owl-carousel

i have developed aspx page
on it i have image galley using owl-carousel
now when i added magnific-popup plugin and used gallery option
then i noticed when i click on image on carousel it get popup successfully but images get duplicated (inside popup)
Owl-Carousel gallery
First popup
Duplicated Image
my aspx code :
<div class="owl-carousel">
<asp:ListView runat="server" ID="lvDesrtProgramGallery" ItemType="SharedKernel.Core.Model.ProgramPhoto" SelectMethod="lvDesrtProgramGallery_GetData">
<ItemTemplate>
<div class="item">
<a class="desert-safari-gallery" href="<%# Item.PhotoPath %>">
<img src="<%# Item.MediumPhotoPath %>" alt="" />
<div class="overlay">
<i class="fa fa-search-plus"></i>
</div>
</a>
</div>
</ItemTemplate>
</asp:ListView>
</div>
Js code
$('.desert-safari .owl-carousel').owlCarousel({
items: 3,
dots: false,
nav: true,
loop: true,
margin: 10,
autoplay: true,
navText: ['<i class="fa fa-angle-left fa-4x"></i>', '<i class="fa fa-angle-right fa-4x"></i>'],
onInitialized: callback,
responsiveClass: true,
responsive: {
0: {
items: 1,
nav: false,
margin: 80
},
570: {
items: 1,
nav: false
},
768: {
items: 2,
nav: false
},
992: {
items: 3,
nav: false,
},
1200: {
items: 3,
nav: true,
loop: false
}
}
});
function callback(event) {
$(".desert-safari-gallery").magnificPopup({
type: "image",
removalDelay: 160,
loop: false,
preloader: false,
fixedContentPos: true,
showCloseBtn: false,
gallery: {
enabled: true
}
})
}
I just ran into this problem so I thought I'd give you my answer/solution.
The Reason:
Since your using owl carousel to loop, owl carousel is cloning items. Because your cloning the items within your carousel you're now feeding duplicates into the popup gallery. What a hassle right? There are two seemingly obvious solutions.
Solution 1: Don't use owl-carousel's loop.
This may not be the preferred solution if you want the looping feature of your carousel but this will no longer cause the popup to receive duplicate entries.
Solution 2: Create an array of objects based on the resulting elements, remove the duplicates, then use magnific's items property to set the gallery items.
Here is a working script I had to create based off a similar scenario I'm sure you can dissect what the process is:
(function( $ ) {
'use strict';
$( window ).load(function(){
var GalleryItems = [];
$('.gallery img').each(function(i){
var src = $(this).attr('href');
var theSrc = {
src: src,
type: 'image'
};
GalleryItems.push(theSrc);
});
var GalleryItems = GalleryItems.reduce(function(previous, current) {
var object = previous.filter(object => object.src === current.src);
if (object.length == 0) {
previous.push(current);
}
return previous;
}, []);
theGallery();
function theGallery(){
$('gallery').magnificPopup({
type: 'image',
gallery: {
enabled:true
},
items:GalleryItems,
});
}
});
})( jQuery );
I found that #Chris Stage's answer works perfectly, but for some n00bs who try to use the code verbatim may run into issues. I can't just leave a comment or accept the answer so I am posting my revision in hopes that it provides someone else with the correct code.
The one issue I found was that in the .each() function, that you have to target the wrapping a tag's URL to the larger image, not the image's URL itself due to the fact that the one used in the carousel may be a thumbnail or equivalent, and the larger one to the "larger image" to open in a popup may be a separate URL.
(function( $ ) {
'use strict';
$( window ).load(function(){
var GalleryItems = [];
$('.photo-gallery .item a').each(function(i){ //Target your wrapping a tag
var src = $(this).attr('href');
var theSrc = {
src: src,
type: 'image'
};
GalleryItems.push(theSrc);
});
var GalleryItems = GalleryItems.reduce(function(previous, current) {
var object = previous.filter(object => object.src === current.src);
if (object.length == 0) {
previous.push(current);
}
return previous;
}, []);
theGallery();
function theGallery(){
$('.photo-gallery').magnificPopup({ //Target parent carousel container
type: 'image',
gallery: {
enabled:true
},
items:GalleryItems,
removalDelay: 300,
mainClass: 'mfp-fade' //Adds magnific's fade effect
});
}
});
})( jQuery );
This solution worked perfectly with Owl's issue with "cloned" images and thanks to #Chris Stage for coming up with this. His answer should be the "Accepted Answer" but I'd also love an Upvote for the clarification so I can earn some Rep points :)
For future reference, here is a much simpeler solution:
$('.owl-item:not(.cloned) * .desert-safari-gallery').magnificPopup(..
Change your selector so that it will not be used for children of elements with the 'owl-item cloned' class.
You can use this little fix.
$('.owl-carousel.with-mfp').each(function () {
var $mfp = $(this);
$mfp.on('click', '.owl-item.cloned a', function (event) {
event.preventDefault();
var self = $(this);
// Dependency on image positions in owl and on unique a.href attrs
$mfp.find('.owl-item:not(.cloned) a').each(function (index) {
if ($(this).attr('href') === self.attr('href')) {
$mfp.magnificPopup('open', index);
}
});
});
$mfp.magnificPopup({
type: 'image',
delegate: '.owl-item:not(.cloned) a',
gallery: {
enabled: true
}
});

Resources