0

I'm using the DocxJS package to create a document. Inside my document, I'm trying to create a function that will iterate over some front-end props and create multiple paragraphs for each object inside the array. Whenever I iterate over the array and console.log it, it's working properly. When I do the same thing and try to use the return statement to write the "new Paragraph" as it states in the documentation, it's not working properly and returns nothing.

Here is the package and documentation: Package: https://www.npmjs.com/package/docx Documentation: https://docx.js.org/#/

My array markup looks like this:

[{item}, {item}, {item}]

The objects inside the array are:

{item.value, item.description, item.tags}

Here is the function I've created:

const createItem = () => {
    let itemArray = this.props.goods.products.items;
    console.log(itemArray);

    // This will properly console.log the item description for each one (3 total)
    itemArray.forEach((item) => {
        console.log(item.description);
    })

    // This doesn't return anything, but the console.log DOES return the item descriptions like before
    itemArray.forEach((item) => {
         return new Paragraph({
             text: `${item.description}`,
             alignment: AlignmentType.CENTER,
             style: 'educationDegree'
         }, console.log(item.description));
    })
}

Later on in my document that I'm creating with the docx package, I'm just calling the function like this: createItem()

I've tried passing in, createItem(this.props.goods.products.items) but it does nothing. I've tried doing: this.createItem(this.props.goods.products.items) and it just returns that this.createItem is not a function.

I just can't figure out why this isn't working properly and returning the item.description for each item as it iterates over the array? Currently it returns nothing but the console logs I'm requesting.

Heretic Monkey
  • 11,687
  • 7
  • 53
  • 122
Buckyx55
  • 434
  • 5
  • 23
  • 2
    Think about what function `return new Paragraph({` is happening inside. And note how you're using `forEach`, not `map`. – Carcigenicate Nov 18 '19 at 18:43
  • 3
    The `.forEach()` method ignores values returned from the callback. – Pointy Nov 18 '19 at 18:47
  • @Carcigenicate Sorry I fixed the title to reflect forEach. When I don't loop over anything and JUST do the return new Paragraph({}) etc. It works properly. So something's breaking in the .forEach(). – Buckyx55 Nov 18 '19 at 18:48
  • @Pointy So what would you suggest I use? A .map()? Sorry I'm unfamiliar. – Buckyx55 Nov 18 '19 at 18:48
  • 1
    What are you trying to do? `.map()` will create a new array from the contents (modified by the callback) of an existing array. – Pointy Nov 18 '19 at 18:49
  • 1
    @Buckyx55 No, what I meant is that the `return` is not happening inside `createItem`; it's happening inside the lambda that you pass to `foreach`. You can't return from an outer function inside an inner function. I *think* you might want to change the `foreach` to a map, then do `return itemArray.map((item) =>... ` – Carcigenicate Nov 18 '19 at 18:50
  • @Pointy I'm trying to iterate over all the objects within the array and then create a new Paragraph({}) for each item's descriptions. – Buckyx55 Nov 18 '19 at 18:50
  • @Buckyx55 Please have a look on this: https://stackoverflow.com/questions/6260756/how-to-stop-javascript-foreach – Ashwamegh Nov 18 '19 at 18:51
  • 1
    And from `createItem` you want to return an array of paragraphs? Then you want `map`. – deceze Nov 18 '19 at 18:52
  • Array.prototype.forEach() always returns void no matter what use Array.prototype.map() or write a custom function that takes in an array and returns a new array(not a reference to the one you passed) you can refer mdn [link](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array) – pavan kumar Nov 18 '19 at 18:53
  • @deceze I don't want an array to be returned. I just want to duplicate the new Paragraph({}) three times with the different item.descriptions for each, and then place those in the document where I'm calling the createItem() function, if that makes sense. Would it be better if it was a for loop for that purpose? – Buckyx55 Nov 18 '19 at 18:59
  • @Buckyx55 Where are you using `createItem` function? - If you don't want to return array then it'll be easier to answer if we know how it is being used. – ppgowda4 Nov 18 '19 at 19:08
  • @ppgowda4 In the document I'm creating, I'd like to iterate over each object within the array. I then want to create a "new Paragraph({})" for each one. So in essence, I'd like it to take the array, and then return: "new Paragraph({})", "new Paragraph({})", in the code. (with the Paragraph being filled out). – Buckyx55 Nov 18 '19 at 19:25
  • @Buckyx55 I think returning an array is the way to go. You can iterate over array to render it or whatever you want to do. I think **Chris GW Green**'s answer solves your problem – ppgowda4 Nov 18 '19 at 19:30

2 Answers2

2

Something like this should work for you:

const itemArray = [{description: 'Lorem ipsum'}, {description: 'Lorem ipsum'}]

const AlignmentType = {
   CENTER: 'center'
}

class Paragraph {
  constructor(text, alignment, style) {
    this.text = text
      this.alignment = alignment
      this.style = style
  }
}

const paragraphArray = itemArray.reduce((acc, item) => [...acc, new Paragraph(item.description, AlignmentType.CENTER, 'educationDegree')],[])
Chris GW Green
  • 1,145
  • 9
  • 17
  • Thanks for the answer. When I console.log(paragraphArray), it's properly showing the paragraphs in the array, but when I download the word doc it's not showing anything. Do I have to return the array in the document markup somehow or in the function after you've created the paragraphArray? Thank you for your help! – Buckyx55 Nov 18 '19 at 19:54
0

Array.prototype.forEach() always returns void no matter what use Array.prototype.reduce() or write a custom function that takes in an array and returns a new array(not a reference to the one you passed) you can refer mdn MDN Array

you can see that return value for forEach is always undefined mentioned in docs I suggest you use Array.prototype.reduce()

   let resArr = itemArray.reduce((acc,item) =>{
             let para = new Paragraph({
                 text: `${item.description}`,
                 alignment: AlignmentType.CENTER,
                 style: 'educationDegree'
             })
             acc.push(para)
             return acc;
        },[]);

it is good practice to get new object instead of mutating existing referenced object so thought this would help.

pavan kumar
  • 823
  • 6
  • 15
  • hey sorry did not see that yup i meant to use reduce not map i was going through the comments and missed that, thanks for reminding me i will correct it – pavan kumar Nov 18 '19 at 19:04