Skip to content

Instantly share code, notes, and snippets.

@e-schultz
Created January 29, 2015 12:47
Show Gist options
  • Select an option

  • Save e-schultz/5c3ed30a3d305f6fd327 to your computer and use it in GitHub Desktop.

Select an option

Save e-schultz/5c3ed30a3d305f6fd327 to your computer and use it in GitHub Desktop.
Routers and lists and things
  • In the Content setup for 'Dashboard', pretty much moved the actions / list / etc to live under the 'tab'
 dashboard: {
          id: 'dashboard',
          title: 'Dashboard',

          tabs: [{
            label: 'Analytics',
            tab: 'analytics',
            goTo: 'app.page.list({_contentType: \'dashboard\', tab: \'analytics\'})',
            filterHeaders: ['Dashboard', 'State']
          }, {
            label: 'Enterprises',
            tab: 'enterprises',
            goTo: 'app.page.list({_contentType: \'dashboard\', tab: \'enterprises\'})',
            listHeaders: ['ID', 'Enterprise Name', 'Services', 'Agreed EULA'],
            listAction: function (item) {
              Router.gotoEnterprise(item.id);
            },
            actions: [{
              label: 'Create Enterprise',
              icon: 'ion-wrench',
              action: function () {
                $modal.open({
                  templateUrl: 'app/components/modal/create-enterprise-modal/' +
                    'create-enterprise-tpl.html',
                  controller: 'CreateEnterpriseCtrl as ctrl',
                  size: 'lg'
                });

              },
              className: 'btn-success'
          }]
          }]

In the list component, and similar thing was done in the subheader component. I check to see if the content has a tab, then switch around where we load things from. This is a little messy right now and can be cleaned up to not feel so hackey, but I think the general idea is ok.

var tab;
          if (response.tabs) {

            tab = R.filter(R.propEq('tab', Router.getActiveTab()))(response.tabs)[0];
            try {
              listProvider = $injector.get(tab.tab + 'List'); // <--- see notes on this below
            } catch (e) {
              console.log('unable to find list provider');
            }

          }
          angular.extend(vm, {
            filterHeaders: tab ? tab.filterHeaders : response.filterHeaders,
            filterCount: response.filterCount,
            filterAction: response.filterAction,
            filterContent: response.filterItemMock,
            listHeaders: tab ? tab.listHeaders : response.listHeaders,
            listCount: response.listCount,
            listContent: response.listItemMock,
            listAction: tab ? tab.listAction : response.listAction,
            tabs: response.tabs
          });
```javascript

This controller now takes an $injector - although this could/should be pulled out into a helper service. 

Right now, it's only taking it for the tab - although should change it to account for contentType if there is no tab, so like

```javascript
else {
	// no tabs
	 try {
		listProvider = $injector.get(router.getContentType() + 'List'); // <--- see notes on this below
            } catch (e) {
              console.log('unable to find list provider');
            }
}

The idea being - each contentType that needs to have a list, would have a service that followed the naming convention of contenttypeList, and would have a method called getList.

It is upto that service to fetch the data, and format the list properly.

My example enterprisesList

    var formatList = R.map(function (item) {
      return {
        id: item.id,
        labels: [item.id, item.enterpriseName, item.services ? item.services.join(',') : '', item.agreedEula]
      };
    });

    return {
    	getList: function()
    	{
    	return enterprise.get().then(formatList)
    	}
    }

getList should probably take an object called like searchParams or something so we can pass searching/paging/filtering data. But the idea is that each list provider should have the same contract/interface.

Was also playing around a little bit with loading up the details. This is a little hard-coded right now, but can be expanded/cleaned up:

 .state('app.page.list.detail', {
      url: '/:_id',
      views: {
        detail: {
          controller: 'DetailCtrl as detail',
          templateUrl: 'app/sections/detail/detail.html'
        },
        '[email protected]': {
          templateProvider: function ($templateRequest, $stateParams) {
            // TODO: Create a service for this?
            // Have a convention of how to find the correct view
            var path = 'app/sections/detail/default.html';

            if ($stateParams._contentType === 'dashboard' && $stateParams.tab === 'enterprises') {
              path = 'app/sections/detail/dashboard/enterprises/enterprises.html';
            }

            return $templateRequest(path);
          }
        }

      }
    });
  });

The 'detail.html' is now smaller than it was before

<div class="detail-view">
    <div class="detail-view--mask" ng-click="detail.closeDetails()"></div>
    <div class="detail-view--container">

        <div ui-view="detail-view-content"></div>

    </div>
</div>

so similar to having a convention for xyzList - we could try and have a contention for finding templates for the details on the fly.

Currently in the enterprise.html I'm using:

<div ng-controller='EnterpriseDetailCtrl as ctrl'>
<!-- the rest -->
</div>

to get the controller for it - although similar to templateProvider, you could use a controllerProvider function to dynamically return the controller name - although in this case, sort of fine with using the ng-controller in the template.

Theres a few things I'm not happy about with a bit of my file organization - sort of don't like having my create-enterprise stuff tucked under app/components/modal/create, and then list shoved under list, and details tucked under details. Feesls like there is quite a bit of jumping around

Even though we are having this fairly generic routing, still think it'd make sense to have it

- sections
-- enterprise
---- list
---- details
---- create
---- update

There is also quite a bit repetition between my create controller, and my update controller - would like to try and clean it up and pull out the reusable code to an appropiate place.

I'm not a big fan of always re-using the same controller for create,update,view - as almost every time I've tried that because 'they are exactly the same (at the start)' - sure enough things crop up that start being specific to each thing and you get a whole bunch of

if(editMode) 
{ then this } 
else if (createMode)
{ then this }
else if (viewMode)
{ then this }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment