How to retrieve any module fields in a dropdown in sugarcrm?

Hello,

I want to get all fields of a module in a dropdown according to the modules like the Configure button in the ActionButton fields.



After clicking the configure button the drawer will open and in that



Does anyone have an idea about that for the normal module?

Parents
  • I don't have v13 but I would start by looking at the code that generates that dropdown you have as an example.

    The field names are in the metadata.

    You could leverage the /metadata API with type_filter = "modules" and "module_filter" = the name of the module you are interested in, this will give you all the metadata for that module. From there you can extract the "fields" and from there their names their names.

    See Matt Marum's post here:

     3 Tips for using the Sugar Metadata API 

    And possibly do a query based dropdown, there's an example I wrote  some time ago here:

     Create dropdown from module records 


    FrancescaS

  • Hello ,

    Thank you I got that list according to modules and filtered the data.

    I want to ask you one question that was regarding this,

    I created a blank dropdown using Vardefs when I installed a plugin but when I saved the data according to the modules it saved in db but did not reflect on record view.

    for ex:-

    db record



    Record view 



    How do we display the record? 

    The field is multi-select.

  • Good point, in the few places where I use query based dropdowns I do not save the values in the same field, I use the dropdown to populate a text field.

    The reason you are not seeing the values in the front end, even though they exist in the back end, is that the Language files do not have the label=>value translation. Sugar, by default, will display nothing if the value stored in an enum or multi-enum field is not in the corresponding dropdown definition.

    Unfortunately, I did not consider this when responding to your post. I apologize for that.

    My first instinct is that you will need to work with the mulitenum field definition and find a way to dynamically populate the dropdown definition.

     ,  how would you tackle this problem?
    Did I set   in the wrong direction?

  • This can be easily accomplished thru EnumApi project. You will need to configure the field template enum-parent-api accordingly.

    Cheers

    André Lopes
    Lampada Global
    Skype: andre.lampada
  • I am interpreting Andre's code here,  do correct me if I say anything wrong.

    Sugar has some standard field types like "date", "datetime", "dropdown" etc.

    Each has a field type definition.

    You can see the original field types in your 

    clients/base/fields/

    directory, for example clients/base/enum is where the behavior of the "dropdown" type is defined.

    Andre's project adds three custom field types:

    enum-api

    enum-parent-api

    enum-multi-parent-api

    You can see this in the src directory of his project.

    These new field types are extensions of the Enum field type (the Dropdown).

    If you look at the loadEnumOptions function in Andre's scripts as opposed to the one in the core Enum field type you will see that Andre uses a custom API call to get the value->label pairs instead of using a dropdown definition as the core Dropdown and MultiSelect do.

    What this does for you is allow you to use the new type to populate the Options (the label=>value pairs) that you need to show/use the values of your fields in your interface, it's the missing piece to what you have done above.

    To use Andre's code you would add the field types (download and install his files in your own custom directory), do a Quick Repair Rebuild, and follow the example he provides to create your own API to build the value=>label pairs you need.

    In your views you would define the type for your field and the api to use to populate the dropdown.

    You can see in the examples that in his view he has several fields whose type is one of those three custom ones. For example:

    1 => 
            array (
              'id_name' => 'manufacturer_id',
              'label' => 'LBL_MANUFACTURER_NAME',
              'labelModule' => 'Products',
              'name' => 'manufacturer_id',
              'type' => 'enum-api',
              'api' => 'Products/manufacturers',
            ),

    Note that it has a parameter 'api', that is the API that will populate the dropdown values.

    This is a lot of information if you are just starting out. So don't hesitate to ask more questions. I have learned more from questions / answers on the Sugar Club than anywhere else in these past years as a Sugar customer. :)

    Lots to learn here!

    Francesca

  • Hello ,

    I will apply that as well for now  I can show that data without entry in the dropdown list just loading the whole model but I have a question for you.

    If you help me with that

    I added a custom record list for that, and in the js file, I want to populate the data according to the record view for fields in the list view and from the list view to update the record data.

    the js file code is here

    ({
        extendsFrom: 'RecordlistView',
        /**
         * Fields which should not be available to automatically update
         */
        badFields: [
            'deleted',
            'team_count',
            'account_description',
            'opportunity_role_id',
            'opportunity_role_fields',
            'opportunity_role',
            'email_and_name1',
            'dnb_principal_id',
            'email1',
            'email2',
            'email_addresses',
            'email_addresses_non_primary',
            'email_addresses_primary',
            'email_and_name1',
            'primary_address_street_2',
            'primary_address_street_3',
            'alt_address_street_2',
            'alt_address_street_3',
            'portal_app',
            'portal_user_company_name',
            'mkto_sync',
            'mkto_id',
            'mkto_lead_score',
            'cookie_consent',
            'cookie_consent_received_on',
            'dp_consent_last_updated',
            'accept_status_id',
            'sync_key',
            'locked_fields',
            'billing_address_street_2',
            'billing_address_street_3',
            'billing_address_street_4',
            'shipping_address_street_2',
            'shipping_address_street_3',
            'shipping_address_street_4',
            'related_languages',
        ],

        /**
         * Field types which should not be available to automatically update
         */
        badFieldTypes: [
            'link',
            'id',
            'collection',
            'widget',
            'html',
            'htmleditable_tinymce',
            'image',
            'teamset',
            'team_list',
            'email',
            'password',
            'file'
        ],
        initialize: function (options) {
            this._super('initialize', [options]);
            this.listenTo(this.collection, 'data:sync:complete', this.moduleChanged);
            if (this.events) {
                _.extend(this.events, this.customEvents)
            } else {
                this.events = this.customEvents;
            }
        },

        customEvents: {
            'change [data-name="module_name"]': 'moduleChanged',
        },

        /**
         * Event handler for module selection change
         */
        moduleChanged: function() {
            var moduleName = '';
            _.each(this.rowFields, function (field) {
                var moduleData = _.findWhere(field, { name: 'module_name' });
                moduleName = moduleData.value;
            });
            //this._populateAttributes(moduleName);
            this._populateParentAttributes(moduleName);
            /* this.render(); */
        },

        /**
         * Updates the currently selected module fields array with anything that can be updated
         *
         * @param {string} module
         */
        _populateAttributes: function(module) {
            var fields = _.chain(app.metadata.getModule(module).fields).values();
            fields = fields.filter(
                function filterField(field) {
                    return (
                        !_.isEmpty(field.name) &&
                        !_.isEmpty(field.vname) &&
                        !_.contains(this.badFields, field.name) &&
                        !_.contains(this.badFieldTypes, field.type) &&
                        field.link_type !== 'relationship_info' &&
                        field.readonly !== true &&
                        field.calculated !== true
                    );
                }, this
            ).map(function fieldToTuple(field) {
                return [field.name, app.lang.get(field.vname, module)];
            }).value();

            this._attributes = _.object(fields);
            _.each(this.rowFields, (field) => { // Use arrow function to maintain 'this'
                var fieldData = _.findWhere(field, { name: 'field_name' });
                var customModuleId = fieldData.model.id;
                if (Array.isArray(fieldData.value) && fieldData.value.length > 0) {
                    var keyToCompare = fieldData.value[0];
                    for (var key in this._attributes) {
                        if (this._attributes.hasOwnProperty(key)) {
                            if (key == keyToCompare) {
                                var value = this._attributes[key];
                                $(`tr[name="CustomModule_${customModuleId}"] td[data-type="enum"]:eq(1) .list`).html(`
                                    <div class="ellipsis_inline" data-placement="bottom" title="${value}"> ${value}</div>
                                `);
                            }
                        }
                    }
                }
            });
        },

        /**
         * Update the parent module fields array that can be copied over
         *
         * @param {string} module
         */
        _populateParentAttributes: function(module) {
            var fields = _.chain(app.metadata.getModule(module).fields).values();
            fields = fields.filter(
                function filterField(field) {
                    return (
                        !_.isEmpty(field.name) &&
                        !_.isEmpty(field.vname) &&
                        this.badFields.indexOf(field.name) === -1 &&
                        this.badFieldTypes.indexOf(field.type) === -1 &&
                        field.link_type !== 'relationship_info' &&
                        field.studio !== false
                    );
                }, this
            ).map(function fieldToTuple(field) {
                return [field.name, app.lang.get(field.vname, module)];
            }).value();

            this._parentAttributes = _.object(fields);
            _.each(this.rowFields, (field) => { // Use arrow function to maintain 'this'
                var fieldData = _.findWhere(field, { name: 'field_name' });
                var customModuleId = fieldData.model.id;
                if (Array.isArray(fieldData.value) && fieldData.value.length > 0) {
                    var keyToCompare = fieldData.value[0];
                    for (var key in this._parentAttributes) {
                        if (this._parentAttributes.hasOwnProperty(key)) {
                            if (key == keyToCompare) {
                                var value = this._parentAttributes[key];
                                $(`tr[name="CustomModule_${customModuleId}"] td[data-type="enum"]:eq(1) .list`).html(`
                                    <div class="ellipsis_inline" data-placement="bottom" title="${value}"> ${value}</div>
                                `);
                            }
                        }
                    }
                }
            });
        },
    })

    if you figure it out how can we do that?
  • What is your ultimate goal with what you are building?

  • My goal is to get the field setting for that to make a record like which module has a unique field and map through it for future implementation.

  • I'm not following what you are trying to do here.

    The only thing I can see is that you mention three distinct views in the same paragraph: recordlist, record, list.

    I added a custom record list for that, and in the js file, I want to populate the data according to the record view for fields in the list view and from the list view to update the record data.

    Look at the three core views and make sure you are extending the right view.

    clients/base/views/record

    clients/base/views/list

    clients/base/views/recordlist

    Francesca

  • Hello ,

    I want to express my gratitude for your keen attention to my previous explanation, and I wholeheartedly apologize for any ambiguity.

    Allow me to elaborate on my objectives: I've introduced a bespoke recordlist, overriding the core counterpart. The provided code in recordlist.js is designed to exhibit data in the list view, specifically for an enum field lacking a dropdownList.

    My ambition is to dynamically retrieve fields from metadata, aligning with associated modules, and showcase them not only in the record view but also in the list view. This approach aims for adaptability and efficiency.

    Should you have any strategic insights or recommendations to enhance this process, or if there's a specific aspect you'd like further clarification on, your input would be invaluable.

    Thank you for your understanding and collaboration.

    Best regards,
    Kishan

Reply
  • Hello ,

    I want to express my gratitude for your keen attention to my previous explanation, and I wholeheartedly apologize for any ambiguity.

    Allow me to elaborate on my objectives: I've introduced a bespoke recordlist, overriding the core counterpart. The provided code in recordlist.js is designed to exhibit data in the list view, specifically for an enum field lacking a dropdownList.

    My ambition is to dynamically retrieve fields from metadata, aligning with associated modules, and showcase them not only in the record view but also in the list view. This approach aims for adaptability and efficiency.

    Should you have any strategic insights or recommendations to enhance this process, or if there's a specific aspect you'd like further clarification on, your input would be invaluable.

    Thank you for your understanding and collaboration.

    Best regards,
    Kishan

Children
No Data