Reconsider Child Tables
Reconsider Child Tables
- Child Table seems logical for most line items where further processing of row item in child table is limited.
- Consider using a different parent doctype altogether if you need the row item in child table to have own stages and processes.
- In case of API linking. Add a link field to "Parent" doctype on the new created Doctype that acts as line item to "Parent". Both are Parent level doctypes.
HTML Field based customization
Set Options for HTML field in DocType JS
frm.set_df_property(
'process_details_html',
'options',
frappe.render_template('process_checklist_table', {
doc: fetchValues(frm).process_details,
id:
frm.doc.__islocal === 1
? ''
: frm.doc.name + '-process-details',
docstatus: frm.doc.docstatus,
}),
);
Template public/js/templates/process_checklist_table.html
HTML Template
<style>
.table-container {
overflow: auto; /* Enable scrolling */
background-color: #ffffff;
}
.frappe-control .address-box {
background-color: #ffffff;
}
/* Apply styles to the table header */
.table-container table thead {
position: sticky;
top: -20px;
background-color: white;
z-index: 1;
}
</style>
<div class="table-container">
<div class="address-box" style="max-height: 35rem;">
<table class="table table-bordered border-4" style="text-align: center;">
<thead>
<tr>
{% if id && docstatus==0%}
<th><input type="checkbox" class="{{id}}-select-all"></th>
<th>{{ frappe.utils.icon("project-2", "sm") }}</th>
{% endif %}
<th>No.</th>
<th>Document Code</th>
<th>Description</th>
{% if id%}
<th>Standard Template</th>
{% endif %}
<th>File name</th>
<th>Client Upload</th>
<th>Server Upload</th>
<th>Public</th>
<th style="min-width: 7rem;">Upload Date</th>
<th style="min-width: 13rem">Comments / Justification</th>
<th>Track Exception</th>
<th style="min-width: 7rem;">Due Date</th>
<th>Retain/Waive</th>
<th>Approval Required</th>
<th>Send Email</th>
{% if id && docstatus==0%}
<th>{{ frappe.utils.icon("setting-gear", "sm") }}</th>
{% endif %}
</tr>
</thead>
<tbody>
{% for (let i=0; i<doc.length; i++ ){ %} <tr>
{% if id && docstatus==0%}
<!-- Select Row -->
<td style="vertical-align: initial;">
{% if doc[i].track_exception != "Yes"%}
<input type="checkbox" class="{{id}}-select-row">
{% else %}
<input type="checkbox" class="{{id}}-select-row" hidden>
{% endif %}
</td>
<!-- Attachments -->
<td style="vertical-align: initial;">
<input type="file" hidden class="{{id}}-attach-input" />
{% if doc[i].track_exception != "Yes"%}
<a class="{{id}}-attach-file">{{ frappe.utils.icon("attachment", "sm") }}</a>
{% else %}
<a class="{{id}}-attach-file" hidden>{{ frappe.utils.icon("attachment", "sm") }}</a>
{% endif %}
</td>
{% endif %}
<!-- No. -->
<td>{{ i+1 }}</td>
<!-- Document Code -->
<td>
<span
style="display: inline-block; width: 6rem; white-space: nowrap; overflow: hidden !important; text-overflow: ellipsis;">
{%=doc[i].document_code%}
</span>
</td>
<!-- Description -->
<td>
<span
style="display: inline-block; width: 10rem; white-space: nowrap; overflow: hidden !important; text-overflow: ellipsis;">
{%=doc[i].description%}
</span>
</td>
<!-- Standard Template -->
{% if id%}
<td style="vertical-align: middle;">
{% if doc[i].standard_template_s3_key%}
<a class="{{id}}-standard-template-download">
<span
style="width: 8rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; display: inline-block;">
{%=doc[i].standard_template_name%}
</span>
</a>
{% else %}
<a class="{{id}}-standard-template-download" hidden>
</a>
{% endif %}
</td>
{% endif %}
<!-- File Name -->
<td style="vertical-align: middle;">
{% if doc[i].file%}
<a>
<span class=" {{id}}-preview-file"
style="display: inline-block; width: 8rem; white-space: nowrap; overflow: hidden !important; text-overflow: ellipsis;">
{%=doc[i].file_name%}
</span>
</a>
<br>
<a class="{{id}}-remove-file">
<span>
{{ frappe.utils.icon("close", "sm") }}
</span>
</a>
<a class="{{id}}-s3-download" hidden>
<span
style="width: 8rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; display: inline-block;">
{%=doc[i].file_name%}
</span>
</a>
{% else %}
<a hidden>
<span class=" {{id}}-preview-file"
style="display: inline-block; width: 8rem; white-space: nowrap; overflow: hidden !important; text-overflow: ellipsis;">
{%=doc[i].file_name%}
</span>
</a>
<a class="{{id}}-remove-file" hidden>
<span>
{{ frappe.utils.icon("close", "sm") }}
</span>
</a>
<a class="{{id}}-s3-download">
<span
style="width: 8rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; display: inline-block;">
{%=doc[i].file_name%}
</span>
</a>
{% endif %}
</td>
<!-- Client Upload -->
<td>{%=doc[i].client_upload_yes_no%}</td>
<!-- Server Upload -->
<td>{%=doc[i].server_upload_yes_no%}</td>
<!-- Public -->
<td>{%=doc[i].public%}</td>
<!-- Upload Date -->
<td>{%=doc[i].upload_date%}</td>
<!-- Comments / Justification -->
<td>{%=doc[i].comments%}</td>
<!-- Track Exception -->
<td>{%=doc[i].track_exception%}</td>
<!-- Due Date -->
<td>{%=doc[i].due_date%}</td>
<!-- Retain/Waive -->
<td>{%=doc[i].retain_waive%}</td>
<!-- Approval Required -->
<td>{%=doc[i].approval_required%}</td>
<!-- Send Email -->
<td>{%=doc[i].send_email%}</td>
<!-- Edit -->
{% if id && docstatus==0%}
<td style="vertical-align: middle;">
{% if doc[i].track_exception != "Yes"%}
<a class="{{id}}-edit-row">{{ frappe.utils.icon("edit", "sm") }}</a>
{% else %}
<a class="{{id}}-edit-row" hidden>{{ frappe.utils.icon("edit", "sm") }}</a>
{% endif %}
</td>
{% endif %}
</tr>
{% }%}
</tbody>
</table>
</div>
</div>
{% if id %}
<div class="position-relative h-100">
<div style="top: 0; left: 0; margin-bottom: 5px">
{% if docstatus==0%}
<button class="btn btn-xs btn-default {{id}}-add-row">
Add
</button>
<button class="btn btn-xs btn-default {{id}}-remove-row">
Remove
</button>
<button class="btn btn-xs btn-default {{id}}-upload-all">
Upload
</button>
{% else %}
{% endif %}
</div>
<div class="position-absolute" style="top: 0; right: 0;">
<button class="btn btn-xs btn-default {{id}}-email">
{{ frappe.utils.icon("mail", "sm") }}
</button>
</div>
</div>
{% endif %}
JS Button Actions
Set button actions and create Frappe Dialog
function addNewRowEvents(frm) {
$('.' + frm.doc.name + '-common_documents-add-row').unbind();
$('.' + frm.doc.name + '-common_documents-add-row').on('click', function () {
const assetName = 'common_documents';
rowDialog(frm, {}, assetName);
});
}
function rowDialog(frm, defaultValues = {}, assetName, index = null) {
const d = new frappe.ui.Dialog({
title: index !== null ? 'Edit' : 'Add',
fields: getFields(defaultValues, index === null),
primary_action_label: 'Confirm',
primary_action: values => {
// do something with values
},
secondary_action_label: 'Cancel',
secondary_action: () => {
d.hide();
},
});
d.show();
d.fields_dict.document_code.get_query = function () {
return {
filters: [
['Document Code', 'process_execution_checklist', '=', 1],
['Document Code', 'product', '=', frm.doc.product_name],
],
}
};
}