jadjoubran / laravel5-angular-material-starter

Get started with Laravel 5.3 and AngularJS (material)
https://laravel-angular.readme.io/
MIT License
1.66k stars 400 forks source link

Integrate UIGrid md-table #314

Closed num3r06 closed 8 years ago

num3r06 commented 8 years ago

Hi, i',ve resolved all issue for the installation using apache's virtual host and i begin to develop a cms startinf from this template. I've looking for integrate a ui-grid librariy (http://ui-grid.info/) which i've used in another project. I follow all docs step's

flick36 commented 8 years ago

First of all, can you preperly format your code with 3 backticks ` please?

1.- Do you really need to use $scope? 2.- This startes uses EcmaScript 6 so, when you try to acces to this.$scope in

onRegisterApi: function(gridApi) {
    this.$scope.gridApi = gridApi;
    ...
}

well as the error says that's undefined in the function because it doesn't have access to the same this scope you should use an arrow function (() => {}) so your code would look like this:

onRegisterApi: (gridApi) => {
    this.$scope.gridApi = gridApi;
    ...
}

and that way it should work

Also, this startes uses angualar material, so, if you are planning on using it with such library you might want to take a look at some of the issues related on using the 2 libraries for example: https://github.com/angular-ui/ui-grid/issues/3210

num3r06 commented 8 years ago

Ok i must read better on EcmaScript6 :). Now works fine but what grid i must use instead of uigrid? and without $scope uigrid instatation not works angular.js:13550 TypeError: Cannot set property 'data' of undefined at app-4c8b36e3e6.js:527 at processQueue (angular.js:15961) at angular.js:15977 at Scope.$eval (angular.js:17229) at Scope.$digest (angular.js:17045) at Scope.$apply (angular.js:17337) at done (angular.js:11572) at completeRequest (angular.js:11778) at XMLHttpRequest.requestLoaded (angular.js:11711)

What i should use instead of $scope?

flick36 commented 8 years ago

Yeah, first read about how the variables in ES6 works, everything should work if you just remove .$scope from everything for example:

this.$scope.gridOptions1 = {
   ...
}

will look like:

this.gridOptions1 = {
   ...
}

I haven't use ui-grid so i don't really now what it does or what it doesn't what i use for a project of mine it's just a table with material look -> https://github.com/daniel-nagy/md-data-table

num3r06 commented 8 years ago

Without $scope in grid definition not works. However i try another solution for grid Thx for the support

num3r06 commented 8 years ago

I try the md-table and all works fine except the callback function md-on-select. If i use this.$log or another function/lib seems to not defined this is the content of js

class CodaController{
    constructor(API,$log,ToastService,DialogService){
        'ngInject';
        this.API = API;
        this.$log = $log;
        this.ToastService = ToastService;
        this.DialogService = DialogService;
        //
    }

    $onInit(){
        this.selezionata = [];
        this.API.all('segnalazioni').doGET()
            .then((response) => {
            this.segnalazioni = response.data.segnalazioni;
            this.ToastService.show('Segnalazione selzionata con numero ');
            //this.$log.log(this.segnalazioni);
        })
    }
    openDialog (item) {
        this.$log.log(item);
        this.ToastService.error('Selezionata N. '+item.id_segnalazione);
    }
}

export const CodaComponent = {
    templateUrl: './views/app/components/coda/coda.component.html',
    controller: CodaController,
    controllerAs: 'vm',
    bindings: {}
}

and this is the html

<md-toolbar class="md-table-toolbar md-default">
  <div class="md-toolbar-tools">
    <span>Elenco segnalazioni</span>
  </div>
</md-toolbar>
<md-table-container>
                <table md-table md-row-select="true" ng-model="vm.selezionata">
                    <thead md-head>
                        <tr md-row>
                            <th md-column>Numero</th>
                            <th md-column>Coda</th>
                            <th md-column>Procedura</th>
                            <th md-column>Data</th>
                            <th md-column>Telefono</th>
                            <th md-column>Problema</th>
                        </tr>
                    </thead>
                    <tbody md-body>
                        <tr md-row md-select="segnalazione" md-auto-select="true" md-select-id="id_segnalazione" ng-repeat="segnalazione in vm.segnalazioni | orderObject:'coda'" md-on-deselect="vm.openDialog" md-on-select="vm.openDialog">
                            <td md-cell>
                                {{segnalazione.id_segnalazione}}
                            </td>
                            <td md-cell>{{segnalazione.coda}}</td>
                            <td md-cell>{{segnalazione.id_procedura}}</td>
                            <td md-cell>{{segnalazione.data_segnalazione_ita}}</td>
                            <td md-cell>{{segnalazione.telefono}}</td>
                            <td md-cell>{{segnalazione.descrizione}}</td>

                        </tr>
                    </tbody>
                </table>

</md-table-container>

of the component and this is the error

angular.js:13642 TypeError: Cannot read property 'log' of undefined
    at Controller.openDialog (app-e27888b3ae.js:617)
    at Controller.self.select (md-data-table.js:953)
    at Controller.self.toggle (md-data-table.js:974)
    at fn (eval at compile (angular.js:14539), <anonymous>:4:386)
    at expensiveCheckFn (angular.js:15628)
    at callback (angular.js:25172)
    at Scope.$eval (angular.js:17378)
    at Scope.$apply (angular.js:17478)
    at HTMLElement.<anonymous> (angular.js:25177)
    at defaultHandlerWrapper (angular.js:3487)
flick36 commented 8 years ago

try this:

class CodaController{
    constructor(API,$log,ToastService,DialogService){
        'ngInject';
        this.API = API;
        this.$log = $log;
        this.ToastService = ToastService;
        this.DialogService = DialogService;
        //
    }

    $onInit(){
        this.selezionata = [];
        this.API.all('segnalazioni').doGET()
            .then((response) => {
            this.segnalazioni = response.data.segnalazioni;
            this.ToastService.show('Segnalazione selzionata con numero ');
            //this.$log.log(this.segnalazioni);
        });

        this.openDialog = (item) => {
            this.$log.log(item);
            this.ToastService.error('Selezionata N. '+item.id_segnalazione);
        }
    }

}

export const CodaComponent = {
    templateUrl: './views/app/components/coda/coda.component.html',
    controller: CodaController,
    controllerAs: 'vm',
    bindings: {}
}
num3r06 commented 8 years ago

Ok works fine...but you can explain this behaviour? thx for support

jadjoubran commented 8 years ago

That's an issue with this being different inside the function And he solved it by using the arrow function from ES6 (or ES2015).. It's called Lexical this

num3r06 commented 8 years ago

ok thx

albertojm commented 8 years ago

Hi,

I'm trying to use md-data-table, and i'm getting this message:

Error: [$injector:unpr] Unknown provider: orderObjectFilterProvider <- orderObjectFilter

index.module.js

angular.module('app', [
    'app.run',
    'app.filters',
    'app.services',
    'app.components',
    'app.directives',
    'app.routes',
    'app.config',
    'app.partials'
]);

angular.module('app.run', []);
angular.module('app.routes', []);
angular.module('app.filters', []);
angular.module('app.services', []);
angular.module('app.config', []);
angular.module('app.directives', []);
angular.module('app.components', [
    'ui.router', 'md.data.table', 'ngMaterial', 'angular-loading-bar',
    'restangular', 'ngStorage', 'satellizer', 'ngFileUpload'
]);

projects-component.html

<md-table-container>
    <table md-table md-row-select="true" ng-model="vm.agencies">
        <thead md-head>
            <tr md-row>
                <th md-column>Nombre</th>
                <th md-column>Dirección</th>
                <th md-column>Teléfono</th>
                <th md-column>Descripción</th>
                <th md-column>País</th>
                <th md-column>Fecha</th>
            </tr>
        </thead>
        <tbody md-body>
            <tr md-row md-select="agencies" md-auto-select="true" md-select-id="id" ng-repeat="agencies in vm.agencies | orderObject:'id'">
                <td md-cell>
                    {{agencies.id}}
                </td>
                <td md-cell>{{agencies.name}}</td>
                <td md-cell>{{agencies.address}}</td>
                <td md-cell>{{agencies.phone}}</td>
                <td md-cell>{{agencies.description}}</td>
                <td md-cell>{{agencies.country}}</td>
                <td md-cell>{{agencies.created_at}}</td>

            </tr>
        </tbody>
    </table>

</md-table-container>

list-projects.component.js

class ListProjectsController{
    constructor(API, $log, ToastService, $state, $auth){

        'ngInject';

        this.API = API;
        this.$log = $log;   
        this.$state = $state;
        this.$auth = $auth;

    }

     $onInit(){
        this.agencies = [];
        this.API.all('agency').doGET()
            .then((response) => {
            this.agencies = response.data.agencies;
        });
    }

}

export const ListProjectsComponent = {
    templateUrl: './views/app/components/list-projects/list-projects.component.html',
    controller: ListProjectsController,
    controllerAs: 'vm',
    bindings: {}
}

Thanks for everything guys.

milocosmopolitan commented 8 years ago

I don't know what you want to achieve with this expression (ng-repeat="agencies in vm.agencies | orderObject:'id'"), what is this filter for? did you wanted to sort? I'm not sure if this is what you want, but according to md-data-table example this is how you sort, limit, and pagination.

<md-table-container>
    <table md-table md-row-select ng-model="selected">
        <thead md-head>
            <tr md-row>
                <th md-column>Nombre</th>
                <th md-column>Dirección</th>
                <th md-column>Teléfono</th>
                <th md-column>Descripción</th>
                <th md-column>País</th>
                <th md-column>Fecha</th>
            </tr>
        </thead>
        <tbody md-body>
            <tr md-row md-select="agency" md-auto-select md-select-id="{{agency.id}}" 
                 ng-repeat="agency in agencies  | orderBy: query.order |
                 limitTo: query.limit: (query.page - 1) * query.limit">
                <td md-cell>{{agency.id}}</td>
                <td md-cell>{{agency.name}}</td>
                <td md-cell>{{agency.address}}</td>
                <td md-cell>{{agency.phone}}</td>
                <td md-cell>{{agency.description}}</td>
                <td md-cell>{{agency.country}}</td>
                <td md-cell>{{agency.created_at}}</td>
            </tr>
        </tbody>
    </table>
</md-table-container>
<md-table-pagination md-limit="query.limit" md-limit-options="limitOptions" 
  md-page="query.page" md-total="{{agencies.length}}" md-page-select></md-table-pagination>

class ListProjectsController{
    constructor(API, $scope){

        'ngInject';

        $scope.selected = [];
        $scope.agencies = API.all('agency').getList().$object;

        $scope.query = {
           order: 'created_at',
           limit: 5,
           page: 1
        };

        $scope.limitOptions = [5, 10, 15, {
            label: 'All',
            value: $scope.agencies.length
        }];

    }
}

export const ListProjectsComponent = {
    templateUrl: './views/app/components/list-projects/list-projects.component.html',
    controller: ListProjectsController,
    controllerAs: 'vm',
    bindings: {}
}
albertojm commented 8 years ago

Thanks @milocosmopolitan, i had to adjust it a little bit:

class ListProjectsController{
    constructor(API){

        'ngInject';

        this.selected = [];
        this.agencies = [];

        this.agencies = API.all('agency').doGET()
            .then((response) => {

            this.agencies = response.data.agencies;

            this.query = {
               order: 'created_at',
               limit: 10,
               page: 1
            };

            this.limitOptions = [5, 10, 15, {
                label: 'All',
                value: this.agencies.length
            }];

            console.log(this.agencies.length);
        });

    }

}

export const ListProjectsComponent = {
    templateUrl: './views/app/components/list-projects/list-projects.component.html',
    controller: ListProjectsController,
    controllerAs: 'vm',
    bindings: {}
}

list-projects-component.html

<md-table-container>
    <table md-table md-row-select ng-model="vm.selected">
        <thead md-head>
            <tr md-row>
                <th md-column>Nombre</th>
                <th md-column>Dirección</th>
                <th md-column>Teléfono</th>
                <th md-column>Descripción</th>
                <th md-column>País</th>
                <th md-column>Fecha</th>
            </tr>
        </thead>
        <tbody md-body>
            <tr md-row md-select="agency" md-auto-select md-select-id="{{agency.id}}" 
                 ng-repeat="agency in vm.agencies  | orderBy: vm.query.order |
                 limitTo: vm.query.limit: (vm.query.page - 1) * vm.query.limit">
                <td md-cell>{{agency.id}}</td>
                <td md-cell>{{agency.name}}</td>
                <td md-cell>{{agency.address}}</td>
                <td md-cell>{{agency.phone}}</td>
                <td md-cell>{{agency.description}}</td>
                <td md-cell>{{agency.country}}</td>
                <td md-cell>{{agency.created_at}}</td>
            </tr>
        </tbody>
    </table>
</md-table-container>
<md-table-pagination md-limit="vm.query.limit" md-limit-options="vm.limitOptions" 
  md-page="vm.query.page" md-total="{{vm.agencies.length}}" md-page-select></md-table-pagination>

Btw my response looks like:

{"errors":false,"data":{"agencies":[{"id":1,"name":"Demarcus Jenkins","address":"2700 Gleichner Ramp\nSouth Augustinefurt, AL 76346-9063","phone":"+2123984609012","description":"Suscipit eaque repudiandae officiis. Est at quae quo cum asperiores ad fugiat.","country":"Anguilla","created_at":"2016-06-26 08:11:19","updated_at":"2016-06-26 08:11:19"}]}}

Everything is working fine now, but i'm getting this messages:

angular.js:13708Error: [orderBy:notarray] Expected array but received: {}

jadjoubran commented 8 years ago

that might be because of the .getList() If you're using response macros just like in the documentation, you'd have to use a regular

.get('').then( (response) => {
    ...
}`
albertojm commented 8 years ago

Hi @jadjoubran i keep getting the same errors

angular.js:13708Error: [orderBy:notarray] Expected array but received: {}

this.projects = API.all('project').get('')
    .then((response) => {

    this.projects = response.data.projects;

    this.query = {
       order: 'created_at',
       limit: 10,
       page: 1
    };

    this.limitOptions = [5, 10, 15, {
        label: 'All',
        value: this.projects.length
    }];

    console.log(this.projects.length);
});

Thanks for all.

jadjoubran commented 8 years ago

Can you try defining projects in your constructor to an empty array:

this.projects = []
albertojm commented 8 years ago

I already have defined it :)

class ListProjectsController{
    constructor(API, $log, ToastService, $state, $auth){

        'ngInject';

        this.selected = [];
        this.projects = [];

        this.projects = API.all('project').get('')
            .then((response) => {

            this.projects = response.data.projects;

            this.query = {
               order: 'created_at',
               limit: 10,
               page: 1
            };

            this.limitOptions = [5, 10, 15, {
                label: 'All',
                value: this.projects.length
            }];

            console.log(this.projects.length);
        });

    }

}

export const ListProjectsComponent = {
    templateUrl: './views/app/components/list-projects/list-projects.component.html',
    controller: ListProjectsController,
    controllerAs: 'vm',
    bindings: {}
}
flick36 commented 8 years ago

Thats because your resposne it's returning a json and restangular expect an array, in your laravel response, convert it to array instead of JSON

albertojm commented 8 years ago

Hi @flick36 I know, i just wanted to keep using response macros, like the docu says :D

flick36 commented 8 years ago

they're you can create your own, the ones included are more generic ones

num3r06 commented 8 years ago

I use doGET instead of get for restangular. So the response it's ready for use

jadjoubran commented 8 years ago

You can probably keep using them.. can you show me the code? We might just have to collect them into an array

num3r06 commented 8 years ago

this is the function in component which receive data and push in the array ready for the table

getCoda(){
        var segnalazioni = [];
        this.API.all('segnalazioni').doGET()
            .then((response) => {
                angular.forEach(response.data.segnalazioni, function(value){
                    segnalazioni.push(value);      
                });
            this.segnalazioni = segnalazioni; 
        })
     }
milocosmopolitan commented 8 years ago

@num3r06 In my opinion pushing each row of json object which already includes array of data seems redundant process.

jadjoubran commented 8 years ago

yeah, true btw @num3r06 sorry I meant can you show the backend code

num3r06 commented 8 years ago

i do this because custom orderBy filter don't work for me and i need a rapid solution, The backend code (laravel side) is quite simple:

public function lista()
    {
        $segnalazioni = Segnalazione::with('user_cliente','cliente')
                    ->where('gestita',0)
                    ->where('bloccato',0)
                    ->orderBy('id_procedura')
                    ->orderBy('data_segnalazione','ASC')
                    ->get();

        return response()->success(compact('segnalazioni'));
    }
jadjoubran commented 8 years ago

@num3r06 can you try ->get()->toArray();

milocosmopolitan commented 8 years ago

@num3r06 calling a request each time user changes sort param will create too many unnecessary request and response between server and client. You can use lodash to do lots of thing with given array or object, in that way you only need to request once.

num3r06 commented 8 years ago

great info...really i don't make any sort for user (it's a ticketing system and the operators MUST take first call in sequence) but this info will very useful for future development

num3r06 commented 8 years ago

where i found a tutorial for using loadash in ES6?

milocosmopolitan commented 8 years ago

Glad it helps. lodash is included as dependency of restangular so when you bower install laravel angular material starter it should be installed as well. You could look at https://lodash.com/docs just to get the idea lodash's features. I mostly use google search to get what I want, something like "array push in lodash" :tongue:

flick36 commented 8 years ago

Sorry but by 'loadash' are we talking about 'lodash'?

milocosmopolitan commented 8 years ago

@flick36 you are correct my bad I updated comment