Custom Bulk menu item in custom module

HI i have followed these instuction on an built in module and it works fine.

https://gist.github.com/pgorod/5de7c6f8d37413654b16e06668d7e1b1

https://gist.github.com/pgorod/c838f258fadf9528b61183e763e978a8

When trying with a module i built i get the following errors.


[Tue Oct 30 14:53:21.679340 2018] [:error] [pid 22124] [client 172.16.1.9:7895] PHP Notice:  Undefined variable: controller in /var/www/html/include/MVC/Controller/ControllerFactory.php on line 83, referer: http://172.16.1.89/index.php?action=ajaxui
[Tue Oct 30 14:53:21.679574 2018] [:error] [pid 22124] [client 172.16.1.9:7895] PHP Fatal error:  Uncaught Error: Call to a member function setup() on null in /var/www/html/include/MVC/Controller/ControllerFactory.php:83\nStack trace:\n#0 /var/www/html/include/MVC/SugarApplication.php(98): ControllerFactory::getController('CoMa_Plots')\n#1 /var/www/html/index.php(52): SugarApplication->execute()\n#2 {main}\n  thrown in /var/www/html/include/MVC/Controller/ControllerFactory.php on line 83, referer: http://172.16.1.89/index.php?action=ajaxui
[Tue Oct 30 14:53:21.907496 2018] [:error] [pid 22122] [client 172.16.1.9:7896] script '/var/www/html/cache/index.php' not found or unable to stat, referer: http://172.16.1.89/cache/themes/SuiteP/css/Dawn/style.css?v=rQSuGegA1ftiv_z5tsfAAw

Any Help would be great.

Version 7.10.9
Sugar Version 6.5.25 (Build 344)

So, the view gets customized, your new option is in the menu, but when you click it, it throws that error?

You have to track what the files for your new custom module have, since you are extending classes and they might be different classes, or already have their own extensions which you can’t simply overlook.

So for example when you say

class CustomAccountsController extends SugarController

this will not play well if the custom module is already extending SugarController. In this case you would have to extend the extension, not the original.

I have published the module so i have access to all of it’s files and code. I have search through every file can not not find any class that extends Sugarcontroller.

am i looking in the right place?

Thanks

I’m afraid I don’t how to help any further, I guess you’ll have to follow those PHP errors where they lead you. Something about the class construction, the overrides, etc., is a bit different for custom modules, so the List view customization needs to be adapted, but I don’t know what it is, sorry :frowning:

I have got this working, so I thought I would share what worked for me.

The Class names seem to have a huge impact. The follow the format mentioned below.

custom/modules//controller.php



<?php
class <modulename>Controller extends SugarController
{
    public function action_displaypassedids() {
        if ( !empty($_REQUEST['uid']) ) {
            $recordIds = explode(',',$_REQUEST['uid']);
            foreach ( $recordIds as $recordId ) {
                $bean = SugarModule::get($_REQUEST['module'])->loadBean();
                $bean->retrieve($recordId);
                echo "Sent Record ID {$bean->id}, name ".$bean->get_summary_text()."";
            }
        }
        sugar_die('');
    } 
}



custom/modules//views/view.list.php


<?php

require_once('include/MVC/View/views/view.list.php');

class Custom<modulename>ViewList extends ViewList
{
    /**
     * @see ViewList::preDisplay()
     */
    public function preDisplay()
    {
        parent::preDisplay();

        $this->lv->actionsMenuExtraItems[] = $this->buildMyMenuItem();
    }

    /**
     * @return string HTML
     */
    protected function buildMyMenuItem()
    {
        global $app_strings;
    
        return <<<EOHTML
<a class="menuItem" style="width: 150px;" href="#" onmouseover='hiliteItem(this,"yes");' 
        onmouseout='unhiliteItem(this);' 
        onclick="sugarListView.get_checks();
        if(sugarListView.get_checks_count() &lt; 1) {
            alert('{$app_strings['LBL_LISTVIEW_NO_SELECTED']}');
            return false;
        }
        document.MassUpdate.action.value='displaypassedids';
        document.MassUpdate.submit();">Send records to a new view!</a>
EOHTML;
    }
}
1 Like

Thanks for sharing, this is useful.

While you’re looking into this - I seem to remember there was a difficulty getting all the passed ids if the user clicks to “select all”. Not just “all displayed in this list”, but really “all”, including the other pages of the list.

Have you tried this? Can you get a complete list, or just a list of the currently displayed items?

Yes. It is only return 20 IDs when there are 32 selected. this is a problem for me!

Have you found a fix for this? Is there way to increase the number or records shown in a list view?

Increasing the number of records in List views is done in Admin / System settings, if I’m not mistaken.

I never found a solution for this issue, no. But I didn’t devote much time to it, I don’t think it should be too hard for someone who understands PHP and the way these parameters are being passed from screen to screen in SuiteCRM.

I remember there were some discussions about this online, since that code in my gists is not mine, it is something I borrowed from the SugarCRM forums, it was like “the official” example of adding an item to the list view’s actions, so there are other people discussing this:

https://www.google.com/search?q=sugarcrm+displaypassedids

Tell me if you do find a solution… thanks

Hi,
I used the suggested approach above with defining a custom controller, which also works fine. I am currently having the problem that I want to return ‘cleanly’ to the list view where I selected the records before.
Two questions:

  1. The sugar_die is obviously not good there but just using a regular return does not return you to the list view. Is there a way to return to the list view I was coming from?

  2. I would like to return to the same page I was coming from. If I have like records that fill 20 pages, and I was on page 3 before and added a few records with my custom bulk select, I would like to continue with selecting additional records afterwards and don’t start over from page 1)

What is your action doing? Instead of going into a different page and returning, perhaps you could just do an Ajax call and never leave the page at all.

My action just picks some fields from the selected records and creates a bean in another module. Nothing fancy but the user would then most likely continue on the next pages of the Listview. If they start over every time on the first page this won’t work. How would this AJAX approach look like ?

In buildMyMenuItem, in the Javascript part, you don’t need to submit the form. Instead, just use JQuery to call $.ajax or $.getJSON to run an action on the controller, one that doesn’t return any view.

I can’t spell it out for you in detail - it’s easy if you’ve done it before, difficult if you haven’t. I learned this by copying code from inlineEdit.php and InlineEdit.js

The controller part is similar to what is above, in this topic. But you don’t need to echo anything, you just do your job and return.

This might also help:

If you prefer to do this without programming see my user profile and follow the link for my PowerWorkflows add-on.

1 Like

Thank you I got it working with an AJAX, I am close now but how do I uncheck the rows selected for mass update? When my call returns the values are still checked and I don’t find the call to remove the checks from the mass update object?

About that, I don’t know about any function you could call.

You can always use Javascript to go find the closest check-boxes and unset them.

BTW, it might be nice if you could share your solution here, once you get it working :+1:

Yes, Sir.
Here it is. I digged around in the SuiteCRM code base to find the routine for clearing the selection.

    class Custom<MODULE>ViewList extends ViewList
    {
    /**
     * @see ViewList::preDisplay()
     */
    public function preDisplay()
    {
        parent::preDisplay();
        $this->lv->actionsMenuExtraItems[] = $this->buildMyMenuItem();
    }
    /**
     * @return string HTML
     */
    protected function buildMyMenuItem()
    {
        return <<<EOHTML
    <a href="javascript:void(0)" class="parent-dropdown-action-handler" id="add-to-newsletter" onclick="
    	sugarListView.get_checks();
    if(sugarListView.get_checks_count() < 1) {
        console.log('No records selected');
        return false;
    }

    	$.ajax({
    		processing: true,
    		serverSide: true,
    		url: 'index.php?module=<MODULE>&action=<ACTION>',
    		type: 'GET',
    		dataType: 'json',
    		data: {
            // this pulls the IDs of the selected records
    			ids: document.MassUpdate.uid.value,
    		},
    		success: function (data) {
    			// do success
    		},
    		error: function (data) {
            // do error
    		},
    		complete: function (e, xhr, settings) {
    			// do complete

    		}});
    		
    	// clear selections on checkboxes
    	// taken from https://github.com/salesagility/SuiteCRM/blob/706fd7b7a87cdcaa5f2114028f9e5dc2b243f65b/jssource/src_files/include/javascript/sugar_3.js
    	inputs = document.MassUpdate.elements;
    	for (i = 0; i < inputs.length; i++) {
    	  if (inputs[i].name == 'mass[]') {
    		inputs[i].checked = 0;
    	  }
    	}
    		">Menu Item</a>
    EOHTML;
    }
    }

The action

 class <MODULE>Controller extends SugarController
     {
     public function action_add_to_newsletter() {
         if ( !empty($_REQUEST['ids']) ) {
             $recordIds = explode(',',$_REQUEST['ids']);
             foreach ( $recordIds as $recordId ) {
                 $bean = SugarModule::get($_REQUEST['module'])->loadBean();
                 $bean->retrieve($recordId);
     				// do something
             }
         }
     		header_remove(); 
     		$arr = array();
     		header('HTTP/1.1 201 Created');
     		echo json_encode($arr);
     }
}
2 Likes