How to add new fields to Doctype Form based on button click in frappe erpnext

Frappe ,Erpnext V15
custom Doctype named : Proposal
Screenshot from 2024-03-24 03-15-30

when add new proposal i have 2 fields percentage and donor
if the percentage value >0 and <100 then
a button named moreprop displayed
when that button clicked it must duplicate both fields percentage and donor ?
i tried these:

  moreprop: function(frm) {
    // Duplicate the donor and percentage fields
    var donor = frm.doc.donor;
    var percentage = frm.doc.percentage;
    var newRow = frm.add_child('proposals_donor_section');
    frappe.model.set_value(newRow.doctype, newRow.name, 'donor', donor);
    frappe.model.set_value(newRow.doctype, newRow.name, 'percentage', percentage);
    frm.refresh_field('proposals_donor_section');
  },
  nextprog: function(frm) {
    // Check if all required fields are filled
    var requiredFields = ['donor', 'percentage'];
    var isFieldsFilled = requiredFields.every(function(field) {
      return frm.doc[field] != null; // Check if the value is not null or undefined
    });

    if (isFieldsFilled) {
      // Show the targeted_programs_and_their_percentage_section field if all required fields are filled
      frm.set_df_property('targeted_programs_and_their_percentage_section', 'hidden', 0);
      frm.refresh_field('targeted_programs_and_their_percentage_section');
    } else {
      frappe.throw('Please fill all the required fields.');
    }
  }
});

then :

  moreprop: function(frm) {
    frappe.run_serially([
      function() {
        // Duplicate the donor and percentage fields
        var donor = frm.doc.donor;
        var percentage = frm.doc.percentage;

        // Check if donor and percentage fields have values
        if (donor && percentage) {
          // Create a new row for each donor and percentage value
          donor.forEach(function(donorValue, index) {
            var newRow = frm.add_child('proposals_donor_section');
            frappe.model.set_value(newRow.doctype, newRow.name, 'donor', donorValue);
            frappe.model.set_value(newRow.doctype, newRow.name, 'percentage', percentage[index]);
          });

          frm.refresh_field('proposals_donor_section');

          // Clear the donor and percentage fields after duplication
          frm.set_value('donor', []);
          frm.set_value('percentage', []);

          // Reset the moreprop button visibility
          frm.set_df_property('moreprop', 'hidden', 1);
          frm.refresh_field('moreprop');
        } else {
          frappe.throw('Please fill in the donor and percentage fields.');
        }
      }
    ]);
  },

then

moreprop: function(frm) {
    frappe.run_serially([
      function() {
        // Duplicate the donor and percentage fields
        var donor = frm.doc.donor;
        var percentage = frm.doc.percentage;
        frappe.throw('first msg');

        // Check if donor and percentage fields have values
        if (donor.length > 0 && percentage.length > 0) {
          frappe.throw('2nd msg');

          // Create a new row for each donor and percentage value
          donor.forEach(function(donorValue, index) {
            var newRow = frm.add_child('proposals_donor_section');
            frappe.model.set_value(newRow.doctype, newRow.name, 'donor', donorValue);
            frappe.model.set_value(newRow.doctype, newRow.name, 'percentage', percentage[index]);
          });

          frm.refresh_field('proposals_donor_section');

          // Clear the donor and percentage fields after duplication
          frm.set_value('donor', []);
          frm.set_value('percentage', []);

          // Reset the moreprop button visibility
          frm.set_df_property('moreprop', 'hidden', 1);
          frm.refresh_field('moreprop');
        } else {
          frappe.throw('Please fill in the donor and percentage fields.');
        }
      }
    ]);
  },

it display first msg but did not duplicate the fields !!!
any help thank you

Could you explain what are you trying to do?

If your scenario only requires a maximum of 4 fields, just add them to the doctype.

donor_1
percentage_1
donor_2 // display & mandatory depends on: eval:doc.percentage_1
percentage_2 // display & mandatory depends on: eval:doc.percentage_1

If you will require a new field everytime the percentage is filled, simply create a child table doctype with the fields donor and percentage and add rows conditionally.

thank you @Yamen_Zakhour for you reply
which i need is :
the button will only be visible if the value of percentage is between 0 and 100
if the button clicked it must duplicate the fields
when there are more than percentage fields added the total values of all percentages must equal 100.
then the button must disappear .

Then you can simply create a child table doctype for this matter and automatically add rows using client script.

I will try your way.
But
I think our Frappe experts can solve it and tell what’s wrong in provided scripts above.
Why is it difficult to solve it without child table?

Thank you

Because I can’t understand why and how are you trying to add a field from the client side? Did you think about database?

1 Like

Hi @Yamen_Zakhour
which needed is as the following
Peek 2024-04-04 22-51

so how could this be achieved using frappe?
hello every on . please tell me how can we do this in frappe? need as you see in the gif i have field that accept percentage value which must be (>=1 value <=100) .if the value is 100 there is no problem .but if <=100 . if 20 we must add new percentage field then enter 50 so the total is 70 so once again add 30 now the total is 100…so and i dont know the exact fields we will need ? how this could be done using Frappe ? how the doctype must be ? thank you

Start by creating a custom doctype, let’s call it “Charity Donation”;

  • Name: Charity Donation
  • :heavy_check_mark: is child

Fields

  • Charity: For scalability purposes, this should be a link field which links to the doctype that holds all your charities. Otherwise it can also be a Select field where you add all your options. – Required – In List View
  • Percentage: Percent – Required – In List View

Now add our newly created child table to your original doctype as a table field.

Now you can do the regular flow but it needs some logic. We’ll use client scripts for that.

To add logic, we need to know when to run this logic. Is it on load, on validate (save) or after adding each row. This depends on your scenario.

For the rest of the logic we’ll need to first create a variable

let total_percentage = 0;

Then we need to add the sum of those rows to our new variable

frm.doc.child_table_fieldname.forEach(row => {
            if (row.percentage) {
                total_percentage += row.percentage;
            }
        });

Finally we need to check our sum, if it is less than 100, add another row.

if(total_percentage < 100) {
            let child = frm.add_child('child_table_fieldname');
            refresh_field('child_table_fieldname');
        }

Edit: the most sensible trigger based on the gif you shared would be after entering the percentage. So it would look something like

'percentage': function(frm, cdt, cdn) 

hi @Yamen
thank you all solutions guided me to the same child table
so i am wondering if this is the only solution on frappe?
any way solved using child tables although there is more work to work with look and feel.

now please see also the following :

sub fields with sub sub filds
outcome contain many outputs each output may contain many activities and indicators
and so on ?
how to solve it ?
thank you

Hi,
Create a custom app if you want to achieve the same.

Ok. You mean such functionallity couldn’t be achieved utilizing the current customization options ?
So even a custom app what frappe options to do so?

Well it can be done with the built-in features however if you are looking to achieve the “same look and feel” it’s easier to develop a custom app rather than attempting to replicate that using JS and CSS via client scripts.

Custom apps are limitless, almost anything is achievable.

Good Luck

Thanks :blush:
Look and feel is not that importance.
Which kind of Doctype that will allow to do the same functions?
How many parents and how many child tables?
Thanks