[Minor Tutor] a Table with Child Table ? Let do the impossible

So you are in the case scenario where:

DocType MainDoc has a field Table with link to DocType MainDoc Item and each MainDoc Item need to have a field Table with MainDoc Item Sub.

Basically you are in “f” word (with past sentence) situation because ERPnext doen’t allow the scenaro of a field Table to have a another field Table.

Bare with me and dont get upset, @saurabh6790 helped me make it work be using an html field, so Let’s DO THIS!!!

Create the following:

DocType MainDoc with field:

  1. Title: Data (dummy one just for the fun)
  2. Html Field: maindocitem_html

DocType MainDoc Item with field:

  1. Title: Data (dummy one just for the fun)
  2. DocMain db hash (docmain_name): Data (will hold MainDoc db hash)
  3. Table field: to MainDoc Item Sub

DocType Child Table MainDoc Item Sub with field:

  1. Title: Data (dummy one)
  2. Some Other: Data


The process: We will use MainDoc html field to render a template that will have a btn “New MainDoc Item” . Also we will loop through the list in the template in other to have edit or delete. Basically we replicate the same functionality with Supplier > Add Address.

One thing that you have to remember is that in order to pass DocMain db hash to the next DocType you need first to save it.

So in maindoc.js

frappe.ui.form.on('MainDoc', {
refresh: function(frm){
if (!frm.doc.__islocal){ 
   console.log("I have need saved!!!")
   $(frm.fields_dict['maindocitem_html'].wrapper).html(" Greeks are awesome but kickapoo sucks")
} else {
   console.log("I am just created w8ing to be saved")

The above code just display or not some html content based on ‘frappe.__islocal’. A not so nice function to tell if the docType is at least once saved… you might see also frappe.is_new.

So we need to render a template with a btn and loop variable

change: $(frm.fields_dict['maindocitem_html'].wrapper).html(" Greeks are awesome but kickapoo sucks")

.html(frappe.render_template("maindoc_list", {'looping_variable': [ 1, 2, 3,]   }))
.find("#btn-newMainDocItem").on("click", function() {
    console.log("You click me, why you are doing this? Iam just button that need its calm")

With some JQuery magic and the frappe.render_template( THE NAME OF THE TEMPLATE, A OBJECT THAT CAN BE USED IN THE TEMPLATE) we need to create the html file.

Go to same folder a ‘maindoc.js’ and create the html ‘maindoc_list.html’ with the following:

<button id="btn-newMainDocItem" class="btn btn-xs btn-default btn-subbom">{{ __("New MaiDoc Item") }}</button>
{%= looping_variable %}

And BOOM!@!!! you have a render template with some variable inside!!!
You might thinking that is this “{%= looping_variable %}”… This is a king of Jinja templating for javascript. Yes, it’s madness, but our @rushabh_mehta (I think) wrote this wrapper.

Now, need to bind the action “find(”#btn-newMainDocItem").on(“click” … " with routing to a New DocMain Item DocType Form and pass the MainDoc hash db to MainDoc Item docmain_name field so when we save we will have a reference to the parent doc in our case MainDoc.

We will need a awesome whitelist (WHITELIST FUNCTION ARE AWESOME USE IT !!!)

def get_subbom_doc(docmain_name):
	doc = frappe.new_doc('DocMain Item')
	doc.docmain_name = docmain_name
	return doc
// after .find("#btn-newMainDocItem").on("click", function() {
var cur_frm_name = frm.doc.name;
	 method: 'myapp.myapp.doctype.maindoc.maindoc.get_maindocitem_doc',
	args : {
		'docmain_name': cur_frm_name
	callback: function(r){
		var doc = frappe.model.sync(r.message);

		frappe.set_route("Form", r.message.doctype, r.message.name);



That is happing??? First you need to understand why MainDoc Item field docmain_name appear in our callback function… the reason is the use of ‘frappe.model.sync’ that maps the varialbles… So we use the same “namespace” meaning we use MainDocItem field docmain_name in order frappe to do its magic and bind the values.
The next 'frappe.set_route" do that it says… goes to new Form on MainDoc Item …

If you follow along you have to need the MainDoc db hash displaying to MainDoc Item field.

The last part its for you guys to continue…(Learning by doing).

We have a MainDoc with a button that we can Add MainDoc Item (that have a child Table MainDoc Item Sub). After save it a few records… you need to change the “(frappe.render_template(“maindoc_list”, {‘looping_variable’: [ 1, 2, 3,] })” looping variable mapping the MainDoc Item.


And european guys!!! if you came to the conference … I will make this kind of workshops!!!

1 Like

@kickapoo wow …my compiments :wink::grin:

@kickapoo : could you please add some screenshots ,to see how it looks like.


@kickapoo Can you please share your github repo… Thanks…

@Basawaraj_Savalagi Hey, I dont have any repo to share the code but I have good news. I think for version 8 child table of child table will be possible from the core of erpnext.


That will merged after v8!


@rmehta any chance to get child table of child table aka grand child in v. 9?

I have this implemented here… GitHub - rmehta/frappe at grand-children

But don’t have a use-case yet!


@rmehta Maybe the alternative BOM Lines might be a use case

1 Like

@rmehta i see …i’ve an use case for an application to build using frappe, would be possible to merge it in develop?

Hi @rmehta

This is very useful if you have more details for Item master.

In Item Master, I have to specify which other items can replace the main item.
I put this info and list in a table called Alternate Items.

In any transaction, especially in Opportunity, I need to know if an item has Alternate Items and I have to show this table in Opportunity Item as a read-only field, for reference so that my purchaser will see which items can be purchased in replacement of main item.

I hope this can be considered a valid use-case.

1 Like

Of course there are use cases, but who will build the alternative item feature?

Sorry, I’m not getting your point; is that a matter of who and how many people will use that feature to build erpnext features?

My point is that most people will use it in “custom apps”. That is no incentive for me to add that feature.

The quality and quantity of contribution is still very low. If you want features, you should start contributing first!!

1 Like

@rmehta the people are not contributing, i think, because there is not a clear road map and we/they are not sure that the PR will be merged; probably i’m repeating myself but that what i can see.

I’m using custom app because i need specific features for stock and food retail chain (not exhaustive list):

  • Multi Barcode per Item
  • Import/Export custom records from/to user
  • sync with other ERP and/or other Accountant software
  • More infos in Item Supplier, like item per box, box per pallet, item enabled at supplier side …etc
  • Supplier side charges per item
  • etc. etc. etc.

Other feature i need, and probably other peoples need:

  • Purchase cycle for Product Bundle
  • Promotional Plans
  • Fidelity
  • show title_field in Links

Now, probably i asked you few times, can you assure me that if i send a PR regarding what i need, all this will be merged? If so, I will be more than happy to send a PR, as i’ve done with cron scheduler, options for Barcode Control and other few fix, otherwise i’d need to rewrite code back for a custom app loosing time.

I know for sure that peoples would like to pay to have feature integrated in ERPNext but, again, what about if they will pay and PR will not be merged?

I think you, the core team, have a clear road map in mind …so lets share it and discuss how to improve; once defined will be surely simpler to contribute.

Perhaps having people contributing to add feature in road map would be a good idea, the more people want it the more contribution PR will have.


I have answered this multiple times, but will do so again

  1. You have to follow the contribution guidelines
  2. Your contribution has to be designed in a manner that is useful to most people.

Will your PR get merged in first-try. Probably NO. But if you are willing to take feedback and improve your PR, very high chances it will get merged.

From my POV, anything going in a custom app, HAS NO VALUE TO THE COMMUNITY,
so I have no incentive to help. Developers of custom apps just end up wasting everyone’s time.

What really pisses me off is that most developers of custom apps, have NO INTENTION of contributing anything back.

I think it’s not a matter first-try, but if the feature itself will be merged or not. Let’s have an example:

  • Multiple Barcode: it’s not a big PR, would be possible to write quite fast

My question is, if it will meet guidelines and all stuff, will be merged? Or will that will be closed and not merged because few peoples needs it? That’s my only concern, spend time to build up a PR and then not able to merge because, let’s say, “not in road map” or “most people needs that”

IMHO, you (core team) and we (as foundation members) needs to find out a way to make people contributing in some way …donating, paying for features, developing, testing, answering issues and stuff …so in some way people need to give something back; also as extreme actions …locking custom script and form customization …for not contributors.

At the begin probably, as drawback, ERPNext would loose some users …but at the end of the day …imho not much loose …and this probably will speed up contribution in any of the above ways.

Just my humble opinion …but i get really pissed of features not merged because no contributions …


I am surprised that you don’t even give it a try. It is really an approach to things. If you want to be a contributor or not. You should know by now what PRs get merged and which do not.