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:
- Title: Data (dummy one just for the fun)
- Html Field: maindocitem_html
DocType MainDoc Item with field:
- Title: Data (dummy one just for the fun)
- DocMain db hash (docmain_name): Data (will hold MainDoc db hash)
- Table field: to MainDoc Item Sub
DocType Child Table MainDoc Item Sub with field:
- Title: Data (dummy one)
- Some Other: Data
So,
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")
$(frm.fields_dict['maindocitem_html'].wrapper).empty()
}
}
});
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")
to
$(frm.fields_dict['subbom_html'].wrapper)
.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>
<hr>
{%= 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 !!!)
@frappe.whitelist()
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;
frappe.call({
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.