Trying to create editable child node

I am trying to add product options to my product node. Product options is an array object having name, id and description, so at first when product is created i want it to be populated by json and then i want it to be editable in neos backend and also i want to give the editor option to add new product options, till now I am able to get the product option data and see it in neos backend but it is not editable. Can anyone help me to figure out what I am doing wrong why it is not editable also how to provide editor option to add their own new product option to the editor.
product.yaml

'ProductConfigurator:Document.Product':
  superTypes:
    'Neos.BaseLegacy:Document.Page': true
  options:
    fusion:
      prototypeGenerator: ~
  ui:
    group: 'modules-media'
    label: i18n
    icon: 'icon-dot-circle-o'
    position: 200
    inlineEditable: true
    inspector:
      groups:
        general:
          label: i18n
  childNodes:
    productOptions:
      type: 'Neos.Neos:ContentCollection'
      ui:
        inspector:
          createNew: true
      constraints:
        nodeTypes:
          - 'ProductConfigurator:Content.ProductOption'

  properties:
    id:
      type: string
      ui:
        reloadPageIfChanged: true
        label: i18n
        inspector:
          group: general

ProductOption.yaml

'ProductConfigurator:Content.ProductOption':
  superTypes:
    'Neos.Neos:Document': true
  ui:
    label: 'Product Option'
    icon: 'icon-dot-circle-o'
    inlineEditable: true
  properties:
    productName:
      type: string
      ui:
        label: 'Product Name'
        inlineEditable: true
        inline:
          editorOptions:
            placeholder: 'Enter title here...'
            autoparagraph: false
    productId:
      type: string
      ui:
        label: 'Product ID'
        inlineEditable: true
    productDescription:
      type: string
      ui:
        label: 'Product Description'
        inlineEditable: true

Content/ProductBody.fusion

prototype(ProductConfigurator:Content.ProductBody) < prototype(Neos.Neos:ContentComponent) {
    apiNode = ${ProductConfigurator.getApiData(node)}
    apiData = ${Json.parse(q(this.apiNode).property('apidata'), true)}
    productOptions = ${Json.parse(q(this.apiNode).property('productOption'), true)} 
    @context {
        apiNode = ${this.apiNode}
        apidata = ${this.apiData}
        productOption = ${this.productOptions}
    }

    renderer = ProductConfigurator:Component.ProductBody {
        productOptionsList = Neos.Fusion:Collection {
            collection = ${productOption}
            itemRenderer = ProductConfigurator:Component.ProductOptionBody  {
            productName = ${item.attributeName}
            productId = ${item.articleId}
            productDescription = ${item.shortDesc}
            }
        }

        mainText = Neos.Neos:PrimaryContent {
            nodePath = 'main'
        }
        name = ${apidata.productName}
    }
}

Component/ProductOptionBody
`prototype(ProductConfigurator:Component.ProductOptionBody) < prototype(Neos.Fusion:Component) {

productName = Neos.Neos:Editable {
property = ‘productName’
node = ${props.node}
}
productId = Neos.Neos:Editable {
property = ‘productId’
node = ${props.node}
}

productDescription = Neos.Neos:Editable {
            property = 'productDescription'
            node = ${props.node}
        }
renderer = afx`
    <div class="product-option">
        <p><strong>Name:</strong>{props.productName}</p>
        <p><strong>ID:</strong> {props.productId}</p>
        <p><strong>Description:</strong>{props.productDescription}</p>
    </div>
`

}
I get like this for eg in my neos backend

"Name:testA

ID: 124888

Description:Just for testing

Name:testB

ID: 278115

Description:Just for testing"

I get these in neos backend but these are not editable, also i dont know how to provide option to user to add their own data, can some one help me with this, I am stuck in this for a long time

Hi @pragya.richa,

If I get you right, you would like to do the following:

  1. Create a new document node (product).
  2. Some API is called to get initial values for product options.
  3. These product options should be created as child nodes.
  4. An Editor should be possible to edit the values of those product options and also to create more/other product options or remove existing ones.

Did I get this right?

Besides that: In your prototype(ProductConfigurator:Component.ProductOptionBody) you correctly used the Neos.Neos:Editable prototype, but when using this prototype as the itemRenderer = ProductConfigurator:Component.ProductOptionBody you override the editables with fixed values.

To give you further assistance, I would like to understand your use case better, so maybe you can describe the steps you want to do to achieve what you need.

Yes,you are correct. These are the steps that I want.

  1. Create a document node product.
  2. Create product options which is an array of object(Id, name and description). I dont know which is better option to create it as child node or as properties. Could you please suggest this too based on my use case.
  3. When the products is intially created I want the productOptions to be autopopulated from the API along with other data.
  4. An Editor should be possible to edit the values of those product options and also to create more/other product options or remove existing ones.

Also, can you please tell me how do I fix this(you override the editables with fixed values), I am kind of new to Neos and dont have idea of this. I did these by reading some online resources.

Sry for the late reply. Didn’t get mailed for your answer. Yes, the learning curve for Neos IS steep. But once you’re in to it, you’ll start loving it :blush:

As you also wrote on slack, I will add the link to the slack discussion.

On slack you asked for a button to call the API and create the child nodes. However, I think this is only needed, if you need to update the created options in the future with one click. If you only need them once on creation, you could add a dispatcher that listens for the Creation of product nodes.

Have a look on how to register a dispatcher signal and at the available signals on the content repository.

But you will have to create the option nodes using PHP.

I would prefer new nodes for each product option, as this will give you more features and a better overview. You could also add some additional info for each node, that is not visible to the user (like some internal IDs or a version code).

Could you add some info, what your apiNode is? Is this a real Neos (document node), is it an (external) uri, or is it sth else? Where did you define it?

For the editable properties:
If you create a new node for each option, you can simply use a content collection (could be the existing main content collection) and only need to render each option individually, so sth like this:

prototype(ProductConfigurator:Content.ProductOption) < prototype(Neos.Neos:ContentComponent) {
name = Neos.Neos:Editable {
property = ‘name’
block = false # otherwise a div will be used in backend
}

    # Same for the other properties 

    renderer = afx`
        <div class="product-option">
            <p><strong>Name:</strong> {props.name}</p>
            <!-- other properties -->
        </div>
    `
}

@benjamink : Thank you for the response. I added the “block = false” in the productOption component, somehow its still not editable.

What I asked in slack is little different from the button which I asked here. I need to add two buttons, one is ‘Add new Option’ button which can be used by the editor to create or delete new productOption.
The second button is ‘Refresh button’ which calls the getApiData(node) (I also use this method in the content/ProductBody.fusion to get data for apiNode which I call when first time product is created ). So, my by adding refresh button on right inspector I want to give the option to remove all edited texts and give the user the initial product data which I received from the api.
‘ProductConfigurator.getApiData’ is a helper method in the eel folder it calls the data Api and persists the data in the node and then return that node. This method is also called the first time user creates the product and initial data is getting populated by it.

For ‘AddNewOption’ button I tried to add it like this, but it does not work`

prototype(ProductConfigurator:Content.ProductBody) < prototype(Neos.Neos:ContentComponent) {
    apiNode = ${ProductConfigurator.getApiData(node)}
    apiData = ${Json.parse(q(this.apiNode).property('apidata'), true)}
    productOptions = ${Json.parse(q(this.apiNode).property('productOption'), true)} 
    @context {
        apiNode = ${this.apiNode}
        apidata = ${this.apiData}
        productOption = ${this.productOptions}
    }

    renderer = ProductConfigurator:Component.ProductBody {
        productOptionsList = Neos.Fusion:Collection {
            collection = ${productOption}
            itemRenderer = ProductConfigurator:Component.ProductOptionBody  {
            productName = ${item.attributeName}
            productId = ${item.articleId}
            productDescription = ${item.shortDesc}
            }
        }

        addNewOptionButton = Neos.Fusion:Component {
            component = 'Neos.Neos:Button'
            label = 'Add New Option'
            mode = 'primary'
            onClick = 'window.Neos.Theming.ContentCanvas.openCreateDialog("ProductOption")'
            renderer = afx`
                <div class="add-new-option-button">
                    {props.addNewOptionButton}
                </div>
            `
        }        
mainText = Neos.Neos:PrimaryContent {
            nodePath = 'main'
        }
        name = ${apidata.productName}
    }
}

and created new component for the button as Component/AddNewOptionButton.fusion
prototype(ProductConfigurator:Component.AddNewOptionButton) < prototype(Neos.Fusion:Component) { renderer = afx

{props.label}

}

Hey @pragya.richa,

your product options are already single nodes. So I would suggest to render them inside a Neos.Neos:ContentCollection instead of using a simple Neos.Fusion:Collection, as this will allow you to use the built-in UI to add, remove, copy, move or hide a node, so no custom addNewOptionButton is required here.

For the initial state i would still suggest to use the dispatcher and create the nodes in PHP.

The part to “reset” the product options will require some more work IMO. I would do the following:

  1. Add multiple checks (update or replace, remove custom options or not, … – could be node properties)
  2. Add a custom View for the sidebar with the button to update your options.
  3. Add a Controller and define the required Routing to handle the product option reset.