How can i make my HTML Elements in Gutenberg binded to an Array/Object?
Hi,
i am programming an Gutenberg Block now and just wanted to bind an Object to my Block but it does not update.
Currently i have an list of 's and wanted to be added automatically if i push the "Click me!" Button.
What it does is... If i push on that button, it pushes the new Element into the Array but the Elements are not added. If i click away (if the block loses focus), the elements are added.
What did i do wrong?
edit: props => {
const { setAttributes, attributes } = props;
let slides = props.attributes.slides;
const addSlide = function(event){
slides.push({ title : 'new' });
setAttributes({ slides: slides });
}
return [
<InspectorControls key="inspector">
<PanelBody
title={'Slides'}
initialOpen={true}
>
{slides.map((slide, i) =>
<li key={i}>
{slide.title}
</li>
)}
<Button isPrimary onClick={addSlide}>
Click me!
</Button>
</PanelBody>
</InspectorControls>,
<div className={ props.className } key='richtext'>
{slides.map((slide, i) =>
<li key={i}>
{slide.title}
</li>
)}
<Button isPrimary onClick={addSlide}>
Click me!
</Button>
</div>
];
}
I'm expecting the list elements to add dynamically while foxused.
Related
I want to change the appearance of a button when it its clicked to show an arrow coming out of it. I would like to do it using css. I am building a react application using typescript.
When the next button is clicked the arrow should be removed from the first one and go to the next one.
I have included a picture of the desired outcome.
Here is an example of 2 of the buttons:
<div className="button-container">
<Button
className="text-white font-nunito text active"
onClick={() => onFieldAdd('textField')}
>
<TextFieldsIcon />
<p> Text Box</p>
</Button>
<Button
className="text-white font-nunito text mx-2 pr-15"
onClick={() => onFieldAdd('imageField')}
disabled={!!formId}
>
<AddPhotoAlternateIcon />
<p> Image</p>
</Button>
</div>
This could be the solution you're looking for:
import { useState } from "react";
const YourComponentName = () => {
const [selectedBtn, setSelectedBtn] = useState(null);
const hanldeClick = (e) => setSelectedBtn(e.target.id);
return (
<div>
<button id="btn1" onClick={hanldeClick} className={selectedBtn === "btn1" ? "hasArrow" : ""}>
Button 1
</button>
<button id="btn2" onClick={hanldeClick} className={selectedBtn === "btn2" ? "hasArrow" : ""}>
Button 2
</button>
// SAME THING FOR THE REST OF THE BUTTONS
</div>
)
}
export default YourComponentName;
Just customize it to suit your use case.
Here, I am initializing a state called selectedBtn to null by default, and listening for onClick events on all of the buttons to change that state to the clicked button id. Once it changes, component will rerenders and the CSS class hasArrow will be added to the appropriate button element by checking if selectedBtn state value is equal to the button id, with the help of the ternary conditional operator ?:.
With the help of Lit library we have implemented the component that should render the list with items, where each item is rendered with a separate component:
<div>
<slot name="label"> Here goes the title </slot>
<slot name="list"></slot>
</div>
We pass data to the component like following:
<webc-list ?divided=${true}>
<span slot="label">Title</span>
<ul slot="list">
${items.map(
item =>
html`<webc-list-item
>${item}</webc-list-item
>`,
)}
</ul>
</webc-list>
My question is how can I pass the divided property to the <webc-list-item>.
I tried to access the elements
firstUpdated() {
const dividedProperty = this.divided;
this.renderRoot.querySelector('slot[name=list]')?.assignedElements({ flatten: true })
?.forEach(el => {
if (el && el.tagName && el.tagName.toLowerCase().includes('webc-list-item')) {
el.setAttribute('divided', `${dividedProperty}`);
}
});
But it doesn't work like this, any help would be appreciated!
Accessibility best practices suggest using <button> for button elements.
Prefetching for Next.js can be done via <Link>.
However, when you combine the two and use the Tab key to navigate, it will essentially select that button twice. E.g.
<Link href="#">
<a>
This selects once
</a>
</Link>
<Link href="#">
<a>
<button>
This selects twice
</button>
</a>
</Link>
You could do something like this:
<button
onClick={() => { window.location.href "#" }
>
This only selects once
</button>
But that doesn't prefetch.
You can use router.prefetch to fetch the route before going to the page. Check this for more details
export default function Login() {
const router = useRouter()
const onClick = useCallback((e) => {
router.push('/dashboard')
}, []);
useEffect(() => {
router.prefetch("/dashboard"); // Prefetch the dashboard page
}, [])
return (
<button onClick={onClick}>Login</button>
)
}
this is for nuxt
you don't need to do that way, you can just add props and value into nuxtlink
<NuxtLink
id="home-link"
:to="localePath('/')"
exact
active-class="nav-active"
tag="button"
class="btn btn-primary"
>
Home/Any Name
</NuxtLink>
for next top answer is right
export default function Login() {
const router = useRouter()
const onClick = useCallback((e) => {
router.push('/dashboard')
}, []);
useEffect(() => {
router.prefetch("/dashboard"); // Prefetch the dashboard page
}, [])
return (
<button onClick={onClick}>Login</button>
)
}
When I click on Hello, it redirects ok but to browse back to where i was by clicking back button, it requires 2 back button clicks. (probably because <Link> and <a> are triggered at the same time)
export default function Navigation() {
const router = useRouter()
const menus = [
{ key: 'key1', title: 'title1', clasName: 'class1' },
{ key: 'key2', title: 'title2', clasName: 'class2' },
]
return (
<div role="tablist">
{menus.map(({ key, title, className }) => (
<Link
href={{
pathname: router.pathname,
query: {
menu: key
}
}}>
<a
className={className}
role="tab">
<span>{title}</span>
</a>
</Link>
))}
</div>
)
}
I have to use <a> to apply className.
Only using <a> causes page to rerender even when href is same as current page.
What should I do to prevent 2 history stacks being inserted?
Thanks!
Apparently it was my custom popstate event listener that was pushing an extra stack into History. Thanks all for your comments
I'm trying to show a school's cancelled classes in a select menu. It's arranged by day:
However, my menu just cuts off the overflow text when at a mobile resolution in developer tools.
The thermodynamics class is cut off.
I'm using material ui's select menu with react. Material UI Select documentation I'm also using the menu item. I want to have classes listed overflow onto the next line. The is where I show the classes per day.
This is the code (it's just an example, and it doesn't run):
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<FormControl className={classes.formControl}>
<InputLabel id="demo-controlled-open-select-label" > Filter classes by day</InputLabel>
<Select
labelId="demo-controlled-open-select-label"
id="demo-controlled-open-select"
open={open}
onClose={handleClose}
onOpen={handleOpen}
defaultValue={subjectFilter}
onChange={handleChangeSubject}
className="styleSelect"
>
{item.SUBJECT === 'OPEN_LEARNING' &&
<ul className ="stylingList">
{(state.subjects) && state.subjects.filter(item =>
(item.SUBJECT === 'OPEN_LEARNING')).map(item =>
<li className ="stList">
{item.CLASS_FULL}
</li>
)}
</ul>
}
</MenuItem>
//this is just one day. I do this for all the days.
) )
}
</Select>
</FormControl>
I don't have styles on the classes listed. I just made class names to customize the areas later if needed. I just changed the text color. Thanks. I tried overflow-wrap: break-word; on the li class (stList), but it didn't make the words go to the next line.
TL;DR: Override the wrapping style of the Menu Item:
const useStyles = makeStyles((theme) => ({
root: {
whiteSpace: "unset",
wordBreak: "break-all"
}
}));
//...
const YourComponent =(props)=>{
const classes = useStyles();
//...
<MenuItem classes={{ root: classes.root }}>
}
NL;PR: By default, the menu item style whiteSpace: 'nowrap' prevents the other wraps to apply. You can inspect how the suggested changes work in this pastebin.
Now, your select's menu items will go:
From this:
to this: .
Use ListItem instead of MenuItem:
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<FormControl className={classes.formControl}>
<InputLabel id="demo-controlled-open-select-label" > Filter classes by day</InputLabel>
<Select
labelId="demo-controlled-open-select-label"
id="demo-controlled-open-select"
open={open}
onClose={handleClose}
onOpen={handleOpen}
defaultValue={subjectFilter}
onChange={handleChangeSubject}
className="styleSelect"
>
{item.SUBJECT === 'OPEN_LEARNING' &&
<ul className ="stylingList">
{(state.subjects) && state.subjects.filter(item =>
(item.SUBJECT === 'OPEN_LEARNING')).map(item =>
<li className ="stList">
{item.CLASS_FULL}
</li>
)}
</ul>
}
</ListItem>
//this is just one day. I do this for all the days.
) )
}
</Select>
</FormControl>