pdfme/pdfme

Add DynamicTable Schema

Closed this issue ยท 21 comments

UPDATE



Known Bugs

๐Ÿ”ฅ = priority


This issue is blocked by the following issue:


ref:

MP70 commented

I was reading your schemas/src in order to make modifications needed for my fork anyway and I think from a quick read there's very little actually needed to drop draw-table in if you're fine with it 'as is'. Schema wise, you can just have it pass through the table array and options object directly (minus the fonts and which it looks like you translate from strings) and just use it's types more or less directly, I think we are probably talking something in the order of 100-150 LOC.

However you might then have a case where you have slightly different features for a table cell vs normal 'pdfme' drawn text, for example draw table supports links, and might expose some slightly different syntax for styling text. In a sense it could be more ideal for it to 'call back' to your own standard drawText function, rather than having draw table do the drawing the text itself. That would also enable nested tables. If this route is desired I will need to make a few changes to draw-table but I'm open to it if you can ensure you're able to measure the height/width you need for a cell and draw the text (providing callbacks for both).

One thing to note is that we are measuring text heights/widths in slightly different ways, we can do some testing and see if your method produces better results. Looks like the same results to me, though I've not tested extensively.

For the UI, simply make use of the measuring functions that are exposed. This tells you the width of each column and the height of each row. You can call these separately to the actual 'draw table' function. UI component wise there may be some reusable things I can send you to give a head start, but I am currently not really allowing actual table editing in the drag drop designer other than positioning and reflecting styling/content changes made in a separate component. You might want to take a different approach, but this works best for me.

@MP70

Thank you.
Firstly, regarding the support for links, I hadn't planned to include it in V4, but if it's necessary, I can add it.
#319

The idea of performing drawing via callbacks is very interesting. This means that the table schema would be limited to calculating the layout and style of the table, and the content of the table would be drawn through callbacks, right?

As for measuring the height and width of text, I'm not yet sure which method to use, but generally, the text schema of pdfme, including the dynamic font size feature, works well. It functions correctly not only with Latin characters but also with Japanese and Chinese fonts. However, it's not perfect. There was a recent bug report titled 'Line breaks in RTL languages'.

What I want to clarify is what features this DynamicTable Schema will have. I want to define the requirements before writing any code. I also want to make sure that these features are not overly complex.

Pdfme aims to be a user-friendly PDF library. Therefore, I think it's necessary to discard overly specialized features. The code you've written was originally developed for in-house use and then extracted. Before integrating it into the core library of pdfme, I want to clarify what is necessary and what is not.

Is there a way to check what features the current pdf-lib-draw-table supports and what requirements it had?

MP70 commented

No worries. Apologies for the delay in response, it's been a busy New Year!

"The idea of performing drawing via callbacks is very interesting. This means that the table schema would be limited to calculating the layout and style of the table, and the content of the table would be drawn through callbacks, right?"

Yes. Schema-wise in draw table, it could be a type of cell content to add, similar to how we have customStyledText, or image/link. We might add something like customDrawnContent { MeasureCallback: void, DrawCallback: void}. Otherwise if there is no need to mix and match then it could take a single call back function in 'options' or in place of 'tabledata'. I'd need to have a think about it. On the other hand, draw table already exposes a way of drawing for all primitives except shapes, e.g.,

  • Text,
  • MultiLine Text (where you choose the line breaks),
  • Custom Styled Text,
  • Images,
  • Links,

which you could use today with no modification needed to the draw table library. So if those are acceptable then it's literally just a case of dropping it in.

"As for measuring the height and width of text, I'm not yet sure which method to use, but generally, the text schema of pdfme, including the dynamic font size feature, works well. It functions correctly not only with Latin characters but also with Japanese and Chinese fonts. However, it's not perfect. There was a recent bug report titled 'Line breaks in RTL languages.'"

Fair enough, draw table has only been tested in LTR Latin languages, but RTL and Japanese/Chinese fonts should, in theory, work. A corner case might be on word splitting.

"Pdfme aims to be a user-friendly PDF library. Therefore, I think it's necessary to discard overly specialized features. The code you've written was originally developed for in-house use and then extracted. Before integrating it into the core library of pdfme, I want to clarify what is necessary and what is not."

As it happens, this was actually written from the start as an open-source package. The general idea was that it should be simple to use for a basic use case but enable a decent amount of customization and overriding where the user needed. As such, all 'options' in draw table are exactly that - optional with defaults built in so you can choose to pass an empty options object if you like. It's up to you if you only want to expose a subset of draw table's features to your users. I would recommend exposing some bare minimum things like font, text size, has header, header background, border color, and so on, but it would be your choice. You can see this in the project readme.

@MP70

Thanks for your reply.

I have put together some ideas on how to implement a table in the following article, so please refer to it if you have time.
Implementation Ideas for Dynamic Tables in pdfme

I'm not sure how much of the above ideas can be applied to draw table at this point, but it seems necessary to clarify that.
I will find time to simply incorporate into pdfme what is already achievable with draw table and give it a try.

I will check what kind of UX it will be and, if it looks good, I would like to implement it using draw table as it is.

I will update you if there are any changes.


I have a question.
Is it possible to add width to drawTable?
It is possible to calculate width using startX and pageMargin, but by adding width to drawTable, I think it will be simpler.
In pdfme, the size of the table is determined using the x, y coordinates and width, so it is necessary to be able to specify the width.

Also, it would be more user-friendly if there is an option like cellWidth in jsPDF-AutoTable to specify the width of columns.
โ†‘ I found ColumnOptions.overrideWidths

@MP70
The ability to set a background color for the 'td' element would be beneficial.

My.Movie.mp4

ref: #405

MP70 commented

@MP70 The ability to set a background color for the 'td' element would be beneficial.

My.Movie.mp4
ref: #405

Totally agreed! I think from memory the only reason why I didn't was there was no clear place in the schema to pass it because it's not a table setting, nor a cell content :) It's trivial to add in once I work out the best place for the setting to go as it's already done for the header.

Would per row setting be fine or is per cell be better?

@MP70
At this moment, Setting it up per row is fine.

MP70 commented

@hand-dot

I have a question.
Is it possible to add width to drawTable?
It is possible to calculate width using startX and pageMargin, but by adding width to drawTable, I think it will be simpler.
In pdfme, the size of the table is determined using the x, y coordinates and width, so it is necessary to be able to specify the width.

Yeah I mean the margins were designed to be a more user friendly way of saying 'stop x' and 'stop y' but performing the calculations for the user so they didn't have to.

So for now you can just do page width - startx - table width to arrive at the page margin to pass to draw table. Maybe stopX and stopY would of been simpler after all, could probably add them in as an OR type with page margin, thanks so much for the feedback!

Also, it would be more user-friendly if there is an option like cellWidth in jsPDF-AutoTable to specify the width of columns.

This already exists in overrideWidths: number[] where each number in the array is the width of each column. If you're manually setting column widths then you must provide a width for every column. Is there something about this interface that doesn't work for you, anything I can improve?

@MP70

This already exists in overrideWidths: number[] where each number in the array is the width of each column.
I missed it! Thank you.

Can i see the source code of https://pdf-lib-table-demo.vercel.app/?
I'd like to know how to achieve page break.

@hand-dot could be this one: https://github.com/MP70/pdf-lib-draw-table

edit: wrong link - my bad, didnt checked the repo in detail, saw the mentioned link in the description and assumed this is the related repo ๐Ÿ™ˆ

@hand-dot could be this one: https://github.com/MP70/pdf-lib-draw-table

this is a source code of the pdf-lib-draw-table library, i'd like to know source code of demo app.
i couldn't find behavior of a page break from https://github.com/MP70/pdf-lib-draw-table.

MP70 commented

@hand-dot
Page Break
You're right in that we let users do the page breaking because then they can do it the way they like, rather than imposing 'the one way' but it does provide the tools to make it super simple, and I will be happy to share some examples with you. If we can find a common setting that most users want, without overcomplicating the library it could potentially be in scope for inclusion.

The demo does page breaking if a render fails due to overflowing table, so it is quite simplistic. However I would expect you'd want to know if you're going to overflow a page before you actually send off for rendering the table on a pdf because you might want to know for the designer?

Background Color
I have just popped this in the table options under options.row. I don't really love that home for it, but it gets you what you need. It's an array of color or undefined.
so this

      table.options.row = {
        ...table.options.row,
        backgroundColors: [table.options.header.backgroundColor,undefined,table.options.header.backgroundColor],
      }

would set row 1 to have a color, row 2 no color, and row 3 a color.

NB: This setting is only for non header rows, so index 0 color will be the color applied to row 0 in a no header table, and row 1 in a header table.

MP70 commented

Thats released as 0.0.75, you'll need to upgrade. Here is the interface for backgroundColors https://mp70.github.io/pdf-lib-draw-table/interfaces/RowOptions.html

Hello, thanks for PDFME, I can't wait for this future feature!

Maybe just use simple approach instead of pushing it automatically, maybe let user define max row for each table in a page. something like limit offset in database.

We might need to create repeat for many page but I think it's more straight forward.
Then we just need to check total row and count which page need to be print.

Hey @wiryonolau
Interesting. Can you elaborate on this?

I mean let the user handle all the row count, cell width , row height design adjustment.
If it break the page they will need to readjust the design.

For example :
page 1 - table only 5 row
page 2 - table only 10 row
page 3 - table only 10 row

we then can create 3 version , a template that only use page 1, a template that only use page 1 and 2 and so on.

When providing a data that has 12 row, it means it require template with 2 page.
On loading the data first page will only take first 5 row, second page the rest of the row.

It's a bit stupid but I think it will works for the user.
I would love to have the auto page break when adding new row like excel, but I think it's over complicated for a printout report.

Hey @wiryonolau,
Thank you for the proposal.
I am considering offering an implementation for auto page break.

I have already made some progress: https://add-dynamic-table-schema-332.vercel.app/
It's complex and there are bugs, but I want to proceed in this direction.

One thing I wanted to add in case it hasn't been tracked, but I'm noticing that the placement of the tables in the pdf from Generate PDF sometimes differs from what's on the Designer. This is whenever I add the property to the table schema "readOnly: true", then call "designer.updateTemplate(template)"

The DynamicTable Schema has been released as Beta in pdfme V4.

For more details, please refer to the following documentation:
https://pdfme.com/docs/tables

Hello , @hand-dot do you have any example to share on how to generate the pdf using a template that has a table ?