We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 4172
    • 5,888 Posts
    OK

    Here is a working setup

    This is my schema:

    <?xml version="1.0" encoding="utf-8"?>
    <model package="pscupresets" baseClass="xPDOObject" platform="mysql" defaultEngine="MyISAM" version="1.1">
      <object class="pscuDashboardRole" table="pscu_roles" extends="xPDOSimpleObject">
        <field key="name" dbtype="text" phptype="string" null="true" />
        <composite alias="applications" class="pscuPresetApplication" local="id" foreign="roleId" cardinality="many" owner="local" />
      </object>
      <object class="pscuPresetApplication" table="pscu_rolesPresets" extends="xPDOSimpleObject">
        <field key="roleId" dbtype="int" precision="11" phptype="integer" null="true" />
        <field key="applicationId" dbtype="int" precision="11" phptype="integer" null="true" />
        <aggregate alias="roleOwner" class="pscuDashboardRole" local="roleId" foreign="id" cardinality="one" owner="foreign" />
        <aggregate alias="Application" class="modResource" local="applicationId" foreign="id" cardinality="one" owner="foreign" />
      </object>
    </model>
    


    This is the setup for the CMP:

    {
      "formtabs":[
        {
          "MIGX_id":121,
          "caption":"Role",
          "print_before_tabs":"0",
          "fields":[
            {
              "MIGX_id":476,
              "field":"name",
              "caption":"Role name",
              "description":"",
              "description_is_code":"0",
              "inputTV":"",
              "inputTVtype":"",
              "validation":"",
              "configs":"",
              "restrictive_condition":"",
              "display":"",
              "sourceFrom":"config",
              "sources":"",
              "inputOptionValues":"",
              "default":"",
              "useDefaultIfEmpty":"0",
              "pos":1
            },
            {
              "MIGX_id":477,
              "field":"applications",
              "caption":"Applications",
              "description":"",
              "description_is_code":"0",
              "inputTV":"",
              "inputTVtype":"migxdb",
              "validation":"",
              "configs":"pscu_roleapplications",
              "restrictive_condition":"[[migxIsNewObject]]",
              "display":"",
              "sourceFrom":"config",
              "sources":"",
              "inputOptionValues":"",
              "default":"",
              "useDefaultIfEmpty":"0",
              "pos":2
            }
          ],
          "pos":1
        }
      ],
      "contextmenus":"update||duplicate||remove||movetotop_migx||movetotop_bottom",
      "actionbuttons":"addItem",
      "columnbuttons":"",
      "filters":"",
      "extended":{
        "migx_add":"Add dashboard role",
        "disable_add_item":"",
        "add_items_directly":"",
        "formcaption":"",
        "update_win_title":"",
        "win_id":"pscupresets",
        "maxRecords":"",
        "addNewItemAt":"bottom",
        "multiple_formtabs":"",
        "multiple_formtabs_label":"",
        "multiple_formtabs_field":"",
        "multiple_formtabs_optionstext":"",
        "multiple_formtabs_optionsvalue":"",
        "actionbuttonsperrow":4,
        "winbuttonslist":"",
        "extrahandlers":"",
        "filtersperrow":4,
        "packageName":"pscupresets",
        "classname":"pscuDashboardRole",
        "task":"pscupresets",
        "getlistsort":"",
        "getlistsortdir":"",
        "sortconfig":"",
        "gridpagesize":"",
        "use_custom_prefix":"0",
        "prefix":"",
        "grid":"",
        "gridload_mode":1,
        "check_resid":1,
        "check_resid_TV":"",
        "join_alias":"applications",
        "has_jointable":"yes",
        "getlistwhere":"",
        "joins":"",
        "hooksnippets":"",
        "cmpmaincaption":"Manage Dashboards",
        "cmptabcaption":"Dashboard Roles",
        "cmptabdescription":"Add\/edit dashboard role",
        "cmptabcontroller":"",
        "winbuttons":"",
        "onsubmitsuccess":"",
        "submitparams":""
      },
      "columns":[
        {
          "MIGX_id":1,
          "header":"Id",
          "dataIndex":"id",
          "width":"",
          "sortable":"false",
          "show_in_grid":"0",
          "renderer":"",
          "clickaction":"",
          "selectorconfig":"",
          "renderchunktpl":"",
          "renderoptions":"",
          "editor":""
        },
        {
          "MIGX_id":2,
          "header":"Role Name",
          "dataIndex":"name",
          "width":"",
          "sortable":true,
          "show_in_grid":1,
          "renderer":"",
          "clickaction":"",
          "selectorconfig":"",
          "renderchunktpl":"",
          "renderoptions":"",
          "editor":""
        },
        {
          "MIGX_id":3,
          "header":"Applications",
          "dataIndex":"applications",
          "width":"",
          "sortable":"false",
          "show_in_grid":1,
          "renderer":"this.renderChunk",
          "clickaction":"",
          "selectorconfig":"",
          "renderchunktpl":"[[migxLoopCollection?\n&packageName=`pscupresets`\n&classname=`pscuPresetApplication`\n&joins=`[{\"alias\":\"Application\"}]`\n&where=`{\"roleId\":\"[[+id]]\"}`\n&tpl=`@CODE:[[+Application_pagetitle]]`\n&outputSeparator=`,`\n]]",
          "renderoptions":"",
          "editor":""
        }
      ]
    }
    


    important parts:

    the grid-field, uses the config pscu_roleapplications and is not shown on new objects with the snippet in restrictive_condition
              "inputTVtype":"migxdb",
              "configs":"pscu_roleapplications",
              "restrictive_condition":"[[migxIsNewObject]]",
    


    the snippet 'migxIsNewObject':

    if (isset($_REQUEST['object_id']) && $_REQUEST['object_id']=='new'){
        return 1;
    }



    the applications - column
          "renderer":"this.renderChunk",
          "renderchunktpl":"[[migxLoopCollection?\n&packageName=`pscupresets`\n&classname=`pscuPresetApplication`\n&joins=`[{\"alias\":\"Application\"}]`\n&where=`{\"roleId\":\"[[+id]]\"}`\n&tpl=`@CODE:[[+Application_pagetitle]]`\n&outputSeparator=`,`\n]]",
    

    uses the renderChunk - renderer with a snippet to get the commaseperated applications:
    [[migxLoopCollection?
    &packageName=`pscupresets`
    &classname=`pscuPresetApplication`
    &joins=`[{"alias":"Application"}]`
    &where=`{"roleId":"[[+id]]"}`
    &tpl=`@CODE:[[+Application_pagetitle]]`
    &outputSeparator=`,`
    ]]
    


    the setup for the applications-grid with checkboxes with name 'pscu_roleapplications'
    {
      "formtabs":"",
      "contextmenus":"",
      "actionbuttons":"",
      "columnbuttons":"",
      "filters":"",
      "extended":{
        "migx_add":"",
        "disable_add_item":"",
        "add_items_directly":"",
        "formcaption":"",
        "update_win_title":"",
        "win_id":"pscu_roleapplications",
        "maxRecords":"",
        "addNewItemAt":"bottom",
        "multiple_formtabs":"",
        "multiple_formtabs_label":"",
        "multiple_formtabs_field":"",
        "multiple_formtabs_optionstext":"",
        "multiple_formtabs_optionsvalue":"",
        "actionbuttonsperrow":4,
        "winbuttonslist":"",
        "extrahandlers":"this.handleColumnSwitch",
        "filtersperrow":4,
        "packageName":"pscupresets",
        "classname":"modResource",
        "task":"roleapplications",
        "getlistsort":"",
        "getlistsortdir":"",
        "sortconfig":"",
        "gridpagesize":"",
        "use_custom_prefix":"0",
        "prefix":"",
        "grid":"",
        "gridload_mode":2,
        "check_resid":"0",
        "check_resid_TV":"",
        "join_alias":"",
        "has_jointable":"no",
        "getlistwhere":{
          "parent":239
        },
        "joins":"",
        "hooksnippets":"",
        "cmpmaincaption":"",
        "cmptabcaption":"",
        "cmptabdescription":"",
        "cmptabcontroller":"",
        "winbuttons":"",
        "onsubmitsuccess":"",
        "submitparams":""
      },
      "columns":[
        {
          "MIGX_id":1,
          "header":"ID",
          "dataIndex":"id",
          "width":10,
          "sortable":"false",
          "show_in_grid":1,
          "renderer":"",
          "clickaction":"",
          "selectorconfig":"",
          "renderchunktpl":"",
          "renderoptions":"",
          "editor":""
        },
        {
          "MIGX_id":2,
          "header":"Pagetitle",
          "dataIndex":"pagetitle",
          "width":40,
          "sortable":"false",
          "show_in_grid":1,
          "renderer":"",
          "clickaction":"",
          "selectorconfig":"",
          "renderchunktpl":"",
          "renderoptions":"",
          "editor":""
        },
        {
          "MIGX_id":3,
          "header":"Joined",
          "dataIndex":"joined",
          "width":10,
          "sortable":"false",
          "show_in_grid":1,
          "renderer":"this.renderSwitchStatusOptions",
          "clickaction":"switchOption",
          "selectorconfig":"",
          "renderchunktpl":"",
          "renderoptions":[
            {
              "MIGX_id":1,
              "name":"joined",
              "use_as_fallback":"",
              "value":1,
              "clickaction":"",
              "handler":"",
              "image":"assets\/components\/migx\/style\/images\/cb_ticked.png"
            },
            {
              "MIGX_id":2,
              "name":"unjoined",
              "use_as_fallback":1,
              "value":"0",
              "clickaction":"",
              "handler":"",
              "image":"assets\/components\/migx\/style\/images\/cb_empty.png"
            }
          ],
          "editor":""
        }
      ]
    }
    


    Important parts:

    the column with the renderSwitchStatusOptions - renderer and two renderoptions for the states 'joined/unjoined/'
    which calls the custom processor 'handlecolumnswitch.php' when you click that column
        {
          "MIGX_id":3,
          "header":"Joined",
          "dataIndex":"joined",
          "width":10,
          "sortable":"false",
          "show_in_grid":1,
          "renderer":"this.renderSwitchStatusOptions",
          "clickaction":"switchOption",
          "selectorconfig":"",
          "renderchunktpl":"",
          "renderoptions":[
            {
              "MIGX_id":1,
              "name":"joined",
              "use_as_fallback":"",
              "value":1,
              "clickaction":"",
              "handler":"",
              "image":"assets\/components\/migx\/style\/images\/cb_ticked.png"
            },
            {
              "MIGX_id":2,
              "name":"unjoined",
              "use_as_fallback":1,
              "value":"0",
              "clickaction":"",
              "handler":"",
              "image":"assets\/components\/migx\/style\/images\/cb_empty.png"
            }
          ],
          "editor":""
        }
    


    don't forget to check the extrahandler this.handleColumnSwitch - checkbox:
    "extrahandlers":"this.handleColumnSwitch",
    


    the processor core/components/pscupresets/processors/mgr/roleapplications/handlecolumnswitch.php
    <?php
    
    $config = $modx->migx->customconfigs;
    
    $prefix = $modx->getOption('prefix', $config, null);
    $packageName = $config['packageName'];
    
    $packagepath = $modx->getOption('core_path') . 'components/' . $packageName . '/';
    $modelpath = $packagepath . 'model/';
    
    $modx->addPackage($packageName, $modelpath, $prefix);
    $classname = $config['classname'];
    
    $configs = $modx->getOption('configs', $scriptProperties, 0);
    
    $resource_id = $modx->getOption('resource_id', $scriptProperties, 0);
    $co_id = $modx->getOption('co_id', $scriptProperties, 0);
    $object_id = $modx->getOption('object_id', $scriptProperties, 0);
    
    if (!empty($object_id) && !empty($co_id)) {
        $joinclass = 'pscuPresetApplication';
    
        $fields = array();
        $fields['roleId'] = $co_id;
        $fields['applicationId'] = $object_id;
    
        switch ($scriptProperties['idx']) {
            case '1':
    
                if ($joinobject = $modx->getObject($joinclass, $fields)) {
    
                } else {
                    $joinobject = $modx->newObject($joinclass);
                    //$joinobject->set('pos', $pos);
                    $joinobject->fromArray($fields);
                }
                $joinobject->save();
                break;
            case '0':
                if ($joinobject = $modx->getObject($joinclass, $fields)) {
                    $joinobject->remove();
    
                }
                break;
            default:
                break;
        }
    
    
        //clear cache for all contexts
        $collection = $modx->getCollection('modContext');
        foreach ($collection as $context) {
            $contexts[] = $context->get('key');
        }
        $modx->cacheManager->refresh(array(
            'db' => array(),
            'auto_publish' => array('contexts' => $contexts),
            'context_settings' => array('contexts' => $contexts),
            'resource' => array('contexts' => $contexts),
            ));
    }
    
    
    return $modx->error->success();
    
    


    the processor core/components/pscupresets/processors/mgr/roleapplications/getlist.php
    <?php
    
    //if (!$modx->hasPermission('quip.thread_list')) return $modx->error->failure($modx->lexicon('access_denied'));
    
    $config = $modx->migx->customconfigs;
    
    $prefix = isset($config['prefix']) && !empty($config['prefix']) ? $config['prefix'] : null;
    if (isset($config['use_custom_prefix']) && !empty($config['use_custom_prefix'])) {
        $prefix = isset($config['prefix']) ? $config['prefix'] : '';
    }
    
    if (!empty($config['packageName'])) {
        $packageNames = explode(',', $config['packageName']);
    
        if (count($packageNames) == '1') {
            //for now connecting also to foreign databases, only with one package by default possible
            $xpdo = $modx->migx->getXpdoInstanceAndAddPackage($config);
        } else {
            //all packages must have the same prefix for now!
            foreach ($packageNames as $packageName) {
                $packagepath = $modx->getOption('core_path') . 'components/' . $packageName . '/';
                $modelpath = $packagepath . 'model/';
                if (is_dir($modelpath)) {
                    $modx->addPackage($packageName, $modelpath, $prefix);
                }
    
            }
            $xpdo = &$modx;
        }
    } else {
        $xpdo = &$modx;
    }
    
    $classname = $config['classname'];
    $checkdeleted = isset($config['gridactionbuttons']['toggletrash']['active']) && !empty($config['gridactionbuttons']['toggletrash']['active']) ? true : false;
    $joins = isset($config['joins']) && !empty($config['joins']) ? $modx->fromJson($config['joins']) : false;
    
    $joinalias = isset($config['join_alias']) ? $config['join_alias'] : '';
    
    if (!empty($joinalias)) {
        if ($fkMeta = $xpdo->getFKDefinition($classname, $joinalias)) {
            $joinclass = $fkMeta['class'];
            $joinfield = $fkMeta[$fkMeta['owner']];
        } else {
            $joinalias = '';
        }
    }
    
    
    if ($modx->lexicon) {
        $modx->lexicon->load($packageName . ':default');
    }
    
    /* setup default properties */
    $isLimit = !empty($scriptProperties['limit']);
    $isCombo = !empty($scriptProperties['combo']);
    $start = $modx->getOption('start', $scriptProperties, 0);
    $limit = $modx->getOption('limit', $scriptProperties, 20);
    $sort = !empty($config['getlistsort']) ? $config['getlistsort'] : 'id';
    $sort = $modx->getOption('sort', $scriptProperties, $sort);
    $dir = !empty($config['getlistsortdir']) ? $config['getlistsortdir'] : 'ASC';
    $dir = $modx->getOption('dir', $scriptProperties, $dir);
    $showtrash = $modx->getOption('showtrash', $scriptProperties, '');
    $object_id = $modx->getOption('object_id', $scriptProperties, '');
    $resource_id = $modx->getOption('resource_id', $scriptProperties, '');
    
    //$resource_id = $modx->getOption('resource_id', $scriptProperties, is_object($modx->resource) ? $modx->resource->get('id') : false);
    //$resource_id = !empty($object_id) ? $object_id : $resource_id;
    
    
    $sortConfig = $modx->getOption('sortconfig', $config, '');
    
    if (!empty($sortConfig)) {
        $sort = '';
        if (!is_array($sortConfig)) {
            $sortConfig = $modx->fromJson($sortConfig);
        }
    }
    
    $where = !empty($config['getlistwhere']) ? $config['getlistwhere'] : '';
    $where = $modx->getOption('where', $scriptProperties, $where);
    
    $c = $xpdo->newQuery($classname);
    $c->select($xpdo->getSelectColumns($classname, $classname));
    
    if (!empty($joinalias)) {
        /*
        if ($joinFkMeta = $modx->getFKDefinition($joinclass, 'Resource')){
        $localkey = $joinFkMeta['local'];
        }    
        */
        $c->leftjoin($joinclass, $joinalias);
        $c->select($xpdo->getSelectColumns($joinclass, $joinalias, 'Joined_'));
    }
    
    if ($joins) {
        $modx->migx->prepareJoins($classname, $joins, $c);
    }
    
    /*
    $c->leftjoin('poProduktFormat','ProduktFormat', 'format_id = poFormat.id AND product_id ='.$scriptProperties['object_id']);
    //$c->select($classname.'.*');
    
    $c->select('ProduktFormat.format_id,ProduktFormat.calctype,ProduktFormat.price,ProduktFormat.published AS pof_published');
    */
    
    //print_r($config['gridfilters']);
    
    if (isset($config['gridfilters']) && count($config['gridfilters']) > 0) {
        foreach ($config['gridfilters'] as $filter) {
    
            if (!empty($filter['getlistwhere'])) {
    
                $requestvalue = $modx->getOption($filter['name'], $scriptProperties, 'all');
    
                if (isset($scriptProperties[$filter['name']]) && $requestvalue != 'all') {
    
                    $chunk = $modx->newObject('modChunk');
                    $chunk->setCacheable(false);
                    $chunk->setContent($filter['getlistwhere']);
                    $fwhere = $chunk->process($scriptProperties);
                    $fwhere = strpos($fwhere, '{') === 0 ? $modx->fromJson($fwhere) : $fwhere;
    
                    $c->where($fwhere);
                }
            }
        }
    }
    
    
    if ($modx->migx->checkForConnectedResource($object_id, $config)) {
        if (!empty($joinalias)) {
            $c->where(array($joinalias . '.' . $joinfield => $object_id));
        } else {
            $c->where(array($classname . '.resource_id' => $object_id));
        }
    }
    
    if ($checkdeleted) {
        if (!empty($showtrash)) {
            $c->where(array($classname . '.deleted' => '1'));
        } else {
            $c->where(array($classname . '.deleted' => '0'));
        }
    }
    
    if (!empty($where)) {
        $c->where($modx->fromJson($where));
    }
    
    $count = $xpdo->getCount($classname, $c);
    
    if (empty($sort)) {
        if (is_array($sortConfig)) {
            foreach ($sortConfig as $sort) {
                $sortby = $sort['sortby'];
                $sortdir = isset($sort['sortdir']) ? $sort['sortdir'] : 'ASC';
                $c->sortby($sortby, $sortdir);
            }
        }
    
    
    } else {
        $c->sortby($sort, $dir);
    }
    if ($isCombo || $isLimit) {
        $c->limit($limit, $start);
    }
    
    $configs = $modx->getOption('configs', $scriptProperties, 0);
    
    $joinclass = 'pscuPresetApplication';
    
    $fields = array();
    $fields['roleId'] = $object_id;
    $target_field = 'applicationId';
    
    //get joined Resources
    $resCategories = array();
    $positions = array();
    $c2 = $modx->newQuery($joinclass);
    $c2->where($fields);
    if ($resCategoryCollection = $modx->getCollection($joinclass, $c2)) {
        foreach ($resCategoryCollection as $resCategoryObject) {
            $resCategories[] = $resCategoryObject->get($target_field);
            //$positions[$resCategoryObject->get($target_field)] = $resCategoryObject->get('pos');
        }
    }
    
    //print_r($resCategories);
    
    //$c->sortby($sort,$dir);
    //$c->prepare();echo $c->toSql();
    $rows = array();
    if ($collection = $xpdo->getCollection($classname, $c)) {
        $pk = $xpdo->getPK($classname);
        foreach ($collection as $object) {
            $row = $object->toArray();
            $row['id'] = !isset($row['id']) ? $row[$pk] : $row['id'];
            $row['joined'] = in_array($row['id'], $resCategories) ? '1' : '0';
            //$row['pos'] = $positions[$row['id']];
            $rows[] = $row;
        }
    }
    
    $rows = $modx->migx->checkRenderOptions($rows);
    
    


    I was lazy and copied the default getlist.php - processor from MIGX and just added this lines:
    $joinclass = 'pscuPresetApplication';
    
    $fields = array();
    $fields['roleId'] = $object_id;
    $target_field = 'applicationId';
    
    //get joined Resources
    $resCategories = array();
    $positions = array();
    $c2 = $modx->newQuery($joinclass);
    $c2->where($fields);
    if ($resCategoryCollection = $modx->getCollection($joinclass, $c2)) {
        foreach ($resCategoryCollection as $resCategoryObject) {
            $resCategories[] = $resCategoryObject->get($target_field);
            //$positions[$resCategoryObject->get($target_field)] = $resCategoryObject->get('pos');
        }
    }
    
    //print_r($resCategories);
    
    //$c->sortby($sort,$dir);
    //$c->prepare();echo $c->toSql();
    $rows = array();
    if ($collection = $xpdo->getCollection($classname, $c)) {
        $pk = $xpdo->getPK($classname);
        foreach ($collection as $object) {
            $row = $object->toArray();
            $row['id'] = !isset($row['id']) ? $row[$pk] : $row['id'];
            $row['joined'] = in_array($row['id'], $resCategories) ? '1' : '0';
            //$row['pos'] = $positions[$row['id']];
            $rows[] = $row;
        }
    }
    


    I think, that was it.

    Some similiar setups are here:

    https://github.com/Bruno17/migxNestedNodes
    https://github.com/Bruno17/migxResourceCategories


    [ed. note: Bruno17 last edited this post 8 years, 9 months ago.]
      -------------------------------

      you can buy me a beer, if you like MIGX

      http://webcmsolutions.de/migx.html

      Thanks!