Coder Social home page Coder Social logo

Comments (9)

zackify avatar zackify commented on June 14, 2024 1

boom! thanks for the help

https://github.com/crossfield/gutenblock/blob/master/plugin/src/notes/edit.js

https://github.com/crossfield/gutenblock/releases/tag/0.6.5

from gutenblock.

zackify avatar zackify commented on June 14, 2024

So the repeat field is currently meant to be used in the inspector, mainly because we have too many components to build to make a nice 100% inside gutenberg (without inspector) ui for editing and adding items. But making it work nicey like you want shouldn't take too much. The repeat component just expects to get two props, which the Inspector component passes in: https://github.com/crossfield/gutenblock/blob/master/controls/src/base/inspector.js

If you pass attributes as a prop and an onChange prop, it will work where you want. The reason I made the Inspector component map through props and inject, is because when in the inspector it's not rendered as a child of the component, so i can't use context. Which is what i would have rather done, and it would work in the case of rendering normally, like you are trying to do.

I hope that makes sense but i might not have explained it well.

TLDR; pass in attributes as a prop to repeat when not using Inspector around it and an onChange prop as seen in the Inspector above

const Edit = ({ attributes, setAttributes }) => {
  return (
<Repeat 
    attributes={attributes} 
    onChange={(name, value) => setAttributes({ [name]: value })}
    title="Notes" 
    max="50"
    addNew="Add Field" attribute="notes"
>
    {attributes.notes.map(tab => {
      return <Input name="title" />
    })}
  </Repeat>)

};

from gutenblock.

timarney avatar timarney commented on June 14, 2024

Okay thanks for the insight - going to dig into your source code a bit so I understand better but I get the gist of what you're saying.

from gutenblock.

timarney avatar timarney commented on June 14, 2024

Noting this if others end up trying to do this:

Got this working but had to make changes to Repeat.js . Working now for Inspector + Editor.

@zackify Happy to submit a PR if you like.

Edit.js

const Edit = ({ attributes, setAttributes }) => {
  return (
    <div>
      <Repeat
        attributes={attributes}
        onChange={(name, value) => setAttributes({ [name]: value })}
        setAttributes={setAttributes}
        title="Notes"
        max="50"
        addNew="Add Item" attribute="notes"
      >
        <Input name="title" />
      </Repeat>
    </div>
  )
};

Repeat.js

//added this to push the new item to attributes without this local state gets out of sync 
//i.e. getDerivedStateFromProps doesn't keep up with local state
add() {
        let { attribute, attributes, setAttributes } = this.props;
        let items =
            attributes && attributes[attribute] ? attributes[attribute] : [];
        setAttributes({ [attribute]: [...items, {}] })
}

//render
render() {
        let { items } = this.state;
        let { style, title, addNew, addItem, max, attribute } = this.props;

        let repeats = [];
        for (let item = 0; item < items; item++) {
            repeats.push(this.renderChildren(item));
        }

        return (
            <div style={style}>
                <h1>{title}</h1>
                <div>
                    {repeats}
                    <div style={{ marginTop: '10px' }}>
                        {max > items || !max ? (
                            <Button
                                isPrimary
                                onClick={() => {
                                    this.setState(function (prevState, props) {
                                        return { items: prevState.items + 1 }
                                    }, () => {
                                        this.props.setAttributes && this.add();
                                    })
                                }}
                            >
                                {addNew}
                            </Button>
                        ) : null}
                    </div>
                </div>
            </div>
        );
    }

from gutenblock.

zackify avatar zackify commented on June 14, 2024

I think there’s got to be a better way to make it work without ditching derivedstatefromprops. Otherwise I’d say go for the PR. I am going to copy in all your code and see what’s up and if I can simplify the repeat more for when inside of the editor :)

from gutenblock.

timarney avatar timarney commented on June 14, 2024

Still using getDerivedStateFromProps:

Added add() + calling from add item button click

import React from 'react';

const { Button } = wp.components;

export default class Repeat extends React.Component {
    constructor({ attribute, attributes }) {
        super();
        this.update = this.update.bind(this);
        this.delete = this.delete.bind(this);
        this.add = this.add.bind(this);
        let items =
            attributes && attributes[attribute] ? attributes[attribute] : [];
        this.state = { items: items.length };
    }

    static getDerivedStateFromProps({ attributes, attribute }, state) {
        let items =
            attributes && attributes[attribute] ? attributes[attribute] : [];
        if (items.length !== state.items) return { items: items.length };

        return null;

    }

    add() {
        let { attribute, attributes, setAttributes } = this.props;
        let items =
            attributes && attributes[attribute] ? attributes[attribute] : [];
        setAttributes({ [attribute]: [...items, {}] })
    }

    update(name, value, tabId, onChange) {
        let { attribute, attributes } = this.props;

        let currentAttributes = attributes[attribute] || [];

        let foundAttribute = currentAttributes.find(
            (attr, index) => index === tabId
        );
        let newAttributes;
        if (!foundAttribute)
            newAttributes = [...currentAttributes, { [name]: value }];
        else
            newAttributes = currentAttributes.map(
                (attr, index) => (index === tabId ? { ...attr, [name]: value } : attr)
            );

        return onChange(attribute, newAttributes);
    }

    delete(tabId, onChange) {
        let { attribute, attributes } = this.props;

        let newAttributes = attributes[attribute].filter(
            (attr, index) => index !== tabId
        );

        return onChange(attribute, newAttributes);
    }

    renderChildren(index) {
        let {
            attribute,
            children,
            setAttributes,
            attributes,
            onChange,
        } = this.props;

        return (
            <div
                style={{
                    marginLeft: '10px',
                    marginTop: '15px',
                }}
            >
                {React.Children.map(children, child =>
                    React.cloneElement(child, {
                        key: index,
                        index,
                        setAttributes,
                        attributes:
                            attributes &&
                                attributes[attribute] &&
                                attributes[attribute][index]
                                ? attributes[attribute][index]
                                : {},
                        onChange: (name, value) =>
                            this.update(name, value, index, onChange),
                    })
                )}
                <div onClick={() => this.delete(index, onChange)}>Delete item</div>
            </div>
        );
    }

    render() {
        let { items } = this.state;
        let { style, title, addNew, addItem, max, attribute } = this.props;

        let repeats = [];
        for (let item = 0; item < items; item++) {
            repeats.push(this.renderChildren(item));
        }

        return (
            <div style={style}>
                <h1>{title}</h1>
                <div>
                    {repeats}
                    <div style={{ marginTop: '10px' }}>
                        {max > items || !max ? (
                            <Button
                                isPrimary
                                onClick={() => {
                                    this.setState(function (prevState, props) {
                                        return { items: prevState.items + 1 }
                                    }, () => {
                                        this.props.setAttributes && this.add();
                                    })
                                }}
                            >
                                {addNew}
                            </Button>
                        ) : null}
                    </div>
                </div>
            </div>
        );
    }
}

from gutenblock.

zackify avatar zackify commented on June 14, 2024

from gutenblock.

timarney avatar timarney commented on June 14, 2024

No worries - just noting what I tracked down.

Here's what I'm seeing without my mods (kind of works than ... wipes out the inputs)
screenflow

from gutenblock.

zackify avatar zackify commented on June 14, 2024

from gutenblock.

Related Issues (17)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.