├── .editorconfig ├── .gitignore ├── .npmignore ├── .travis.yml ├── .vscode ├── launch.json ├── settings.json └── tasks.json ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── RELEASING.md ├── circle.yml ├── demo-apps ├── es5 │ ├── index.html │ ├── index.js │ ├── package.json │ ├── readme.md │ └── src │ │ ├── my-table.component.html │ │ └── my-table.component.js ├── es6-systemjs │ ├── index.html │ ├── index.js │ ├── package.json │ ├── readme.md │ ├── src │ │ ├── my-table.component.html │ │ └── my-table.component.js │ └── system.config.js ├── es6-webpack │ ├── .babelrc │ ├── _debug-webpack.js │ ├── index.tpl.html │ ├── package.json │ ├── readme.md │ ├── src │ │ ├── main.js │ │ ├── my-table │ │ │ ├── my-table.component.html │ │ │ └── my-table.component.js │ │ └── shared │ │ │ ├── images │ │ │ └── webpack-logo.png │ │ │ ├── site.scss │ │ │ └── vendor-styles.scss │ └── webpack.config.js └── ts-webpack │ ├── .gitignore │ ├── _debug-webpack.js │ ├── index.tpl.html │ ├── package.json │ ├── readme.md │ ├── src │ ├── app-routing.module.ts │ ├── app.component.html │ ├── app.component.ts │ ├── column-binding-eg │ │ ├── column-binding-eg.component.ts │ │ ├── column-binding-eg.html │ │ ├── column-binding-eg.module.ts │ │ ├── column-binding.scss │ │ ├── column-picker.component.ts │ │ ├── column-picker.html │ │ ├── declarative-table.component.ts │ │ ├── declarative-table.html │ │ ├── dynamic-table..html │ │ └── dynamic-table.component.ts │ ├── grouped-table │ │ ├── grouped-table.component.html │ │ └── grouped-table.component.ts │ ├── main.ts │ ├── my-table │ │ ├── my-table.component.html │ │ └── my-table.component.ts │ ├── shared │ │ ├── demo-data.ts │ │ ├── images │ │ │ └── webpack-logo.png │ │ ├── index.ts │ │ ├── person.ts │ │ ├── site.scss │ │ └── vendor-styles.scss │ └── type-declarations │ │ ├── angular-route.d.ts │ │ └── global.d.ts │ ├── tsconfig.json │ └── webpack.config.js ├── demo-site ├── CNAME ├── app │ └── app.js ├── css │ ├── docs.css │ └── social.css ├── fonts │ ├── glyphicons-halflings-regular.eot │ ├── glyphicons-halflings-regular.svg │ ├── glyphicons-halflings-regular.ttf │ └── glyphicons-halflings-regular.woff ├── index.html ├── js │ ├── angular-social.js │ ├── embed-codepen.min.js │ └── embed-codepen.version.txt └── views │ ├── columns │ ├── demo-reordering.html │ └── demo-visibility.html │ ├── editing │ ├── demo-batch.html │ └── demo-inline.html │ ├── events │ ├── demo-subscribe.html │ └── demo-unsubscribe.html │ ├── filtering │ ├── demo-api.html │ ├── demo-custom-template.html │ ├── demo-customize-algorithm.html │ ├── demo-enabling.html │ ├── demo-filtering-basic.html │ ├── demo-multi-template.html │ ├── demo-nested-property.html │ └── demo-select.html │ ├── formatting │ ├── demo-cell-values.html │ ├── demo-custom-header.html │ ├── demo-dynamic-html-values.html │ ├── demo-dynamic-js-values.html │ ├── demo-header-cell-basic.html │ ├── demo-header-cell-full.html │ └── demo-row.html │ ├── global-customization │ ├── demo-defaults.html │ └── demo-response-interceptors.html │ ├── grouping │ ├── demo-api.html │ ├── demo-enabling.html │ ├── demo-grouping-basic.html │ ├── demo-grouping-fn.html │ └── demo-summary.html │ ├── intro │ ├── demo-real-world.html │ └── overview.html │ ├── loading │ ├── demo-external-array.html │ ├── demo-lazy-loaded.html │ ├── demo-managed-array.html │ └── overview.html │ ├── pagination │ ├── demo-api.html │ └── demo-pager-basic.html │ ├── sorting │ ├── demo-api.html │ ├── demo-enabling.html │ └── demo-sorting-basic.html │ └── todo.html ├── e2e ├── async-await-example.spec.ts ├── builds.spec.ts ├── demo-ng-table.po.ts ├── global.d.ts ├── protractor-travis.config.js ├── protractor.config.js └── tsconfig.json ├── examples-old ├── app │ ├── app.js │ └── main.js ├── css │ ├── bootstrap-theme.min.css │ └── bootstrap.min.css ├── demo15.html ├── demo26.html ├── demo32.html ├── fonts │ ├── glyphicons-halflings-regular.eot │ ├── glyphicons-halflings-regular.svg │ ├── glyphicons-halflings-regular.ttf │ └── glyphicons-halflings-regular.woff └── js │ ├── angular-mocks.js │ ├── angular-resource.min.js │ ├── angular.min.js │ ├── jquery-1.9.1.min.js │ ├── ng-table-export.src.js │ ├── ng-table-resizable-columns.js │ └── require.js ├── index.ts ├── jsconfig.json ├── karma.conf.js ├── npm-shrinkwrap.json ├── package.json ├── scripts ├── open-e2e-report.js └── webpack │ ├── appParts.js │ ├── libParts.js │ ├── multiConfig.js │ └── parts.js ├── src ├── browser │ ├── filterRow.html │ ├── filters │ │ ├── number.html │ │ ├── select-multiple.html │ │ ├── select.html │ │ └── text.html │ ├── groupRow.html │ ├── header.html │ ├── index.ts │ ├── ngTable.directive.ts │ ├── ngTableColumn.ts │ ├── ngTableColumnsBinding.directive.ts │ ├── ngTableController.ts │ ├── ngTableDynamic.directive.ts │ ├── ngTableFilterConfig.ts │ ├── ngTableFilterRow.directive.ts │ ├── ngTableFilterRowController.ts │ ├── ngTableGroupRow.directive.ts │ ├── ngTableGroupRowController.ts │ ├── ngTablePagination.directive.ts │ ├── ngTableSelectFilterDs.directive.ts │ ├── ngTableSorterRow.directive.ts │ ├── ngTableSorterRowController.ts │ ├── pager.html │ ├── public-interfaces.ts │ └── sorterRow.html ├── core │ ├── data │ │ ├── dataSettings.ts │ │ ├── getData.ts │ │ ├── index.ts │ │ ├── interceptor.ts │ │ ├── ngTableDefaultGetData.ts │ │ └── results.ts │ ├── filtering │ │ ├── filterComparator.ts │ │ ├── filterFunc.ts │ │ ├── filterSettings.ts │ │ └── index.ts │ ├── grouping │ │ ├── getGroup.ts │ │ ├── groupSettings.ts │ │ ├── groupingFunc.ts │ │ ├── index.ts │ │ ├── ngTableDefaultGetGroups.ts │ │ └── publicExports.ts │ ├── index.ts │ ├── ngTableDefaults.ts │ ├── ngTableEventsChannel.ts │ ├── ngTableParams.ts │ ├── ngTableSettings.ts │ ├── paging │ │ └── index.ts │ ├── sorting │ │ └── index.ts │ └── util.ts ├── shared │ ├── assign-partial-deep.ts │ ├── check-class-init.ts │ └── index.ts └── styles │ └── ng-table.scss ├── test ├── custom-typings │ ├── jasmine-custom-matchers.d.ts │ └── jasmine-type-fixes.d.ts ├── index.d.ts ├── index.js ├── specs │ ├── filters.spec.ts │ ├── ngTableDefaultGetData.spec.ts │ ├── selectFilterDs.spec.ts │ ├── settings.spec.ts │ ├── table.spec.ts │ ├── tableDynamic.spec.ts │ └── tableParams.spec.ts └── util │ └── jasmine-extensions.ts ├── tsconfig-webpack.json ├── tsconfig.json ├── typedoc.json └── webpack.config.js /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 4 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .temp 2 | .idea 3 | node_modules 4 | out 5 | npm-debug.* 6 | index.js 7 | index.d.ts 8 | index.js.map 9 | src/**/*.js 10 | src/**/*.js.map 11 | src/**/*.d.ts 12 | e2e/**/*.js 13 | e2e/**/*.js.map 14 | e2e/**/*.d.ts 15 | !e2e/**/global.d.ts 16 | !e2e/protractor*.js 17 | !demo-apps/es5/index.js 18 | !demo-apps/es6-systemjs/index.js 19 | test/specs/**/*.d.ts 20 | test/specs/**/*.js.map 21 | test/specs/**/*.js 22 | test/util/**/*.d.ts 23 | test/util/**/*.js.map 24 | test/util/**/*.js 25 | bundles 26 | build 27 | build-stats.json 28 | api-docs -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .vscode/ 2 | .idea/ 3 | .temp/ 4 | # redundant webpack build artifacts produced by ExtractTextPlugin 5 | bundles/styles.* 6 | demo-apps/ 7 | demo-site/ 8 | docs/ 9 | e2e/ 10 | examples-old/ 11 | out/ 12 | scripts/ 13 | *.ts 14 | !*.d.ts 15 | test/ 16 | .editorconfig 17 | *.yml 18 | *.json 19 | *.conf.js 20 | *.config.js -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: node_js 3 | node_js: 4 | - 6.9.1 5 | cache: 6 | directories: 7 | - node_modules 8 | notifications: 9 | email: false 10 | addons: 11 | sauce_connect: true 12 | env: 13 | global: 14 | - secure: gnwapHmalQ00mis28sRZQwmrkOWU7CyIyU3iKc1bixgGKZu6dhMUwQt2WA8HDkOLgSxSCSMigtzwuPvkxH6CRLbMnYwCDkCHZS9SvjrOLX+jZkORbSKRJUjlkRS3cjkY9AzKOYAOngAN07j0iqvsKx6UtdtEvA4QVM/ToQzVfi0= 15 | - secure: J9OuScEujGDV/JKBvOz7pgh/hzA6QEqJKo8wtQprsSuUnP1zdUvlRV+oKuGXAGnfsFlr/aw+7+djz4QbqITQeQDJaQ4Ui4/M8dfDp4kLKGH6U8obrnX79IERjgKZubs17dW+NcbIt6pNzJavOdLlvAZiQtQMcdXbHI+Xa0PoTHs= 16 | 17 | install: 18 | - npm prune && npm install 19 | - npm run setup:ci 20 | 21 | before_script: 22 | - npm run build:demo-apps 23 | - '[ "${TRAVIS_PULL_REQUEST}" = "true" ] || npm run e2e-server:ci' 24 | 25 | script: 26 | - npm test 27 | - '[ "${TRAVIS_PULL_REQUEST}" = "true" ] || npm run e2e:ci' 28 | 29 | after_success: 30 | - cat out/coverage/*/lcov.info | ./node_modules/coveralls/bin/coveralls.js 31 | - npm run semantic-release 32 | 33 | branches: 34 | except: 35 | - "/^v\\d+\\.\\d+\\.\\d+$/" 36 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Launch", 6 | "type": "node", 7 | "request": "launch", 8 | "program": "${workspaceRoot}/demo-apps/es6-webpack/_debug-webpack.js", 9 | "stopOnEntry": true, 10 | "args": [], 11 | "cwd": "${workspaceRoot}", 12 | "preLaunchTask": null, 13 | "runtimeExecutable": null, 14 | "runtimeArgs": [ 15 | "--nolazy" 16 | ], 17 | "env": { 18 | "NODE_ENV": "development" 19 | }, 20 | "externalConsole": false, 21 | "sourceMaps": false, 22 | "outDir": null 23 | }, 24 | { 25 | "name": "Attach", 26 | "type": "node", 27 | "request": "attach", 28 | "port": 5858, 29 | "address": "localhost", 30 | "restart": false, 31 | "sourceMaps": false, 32 | "outDir": null, 33 | "localRoot": "${workspaceRoot}", 34 | "remoteRoot": null 35 | }, 36 | { 37 | "name": "Attach to Process", 38 | "type": "node", 39 | "request": "attach", 40 | "processId": "${command.PickProcess}", 41 | "port": 5858, 42 | "sourceMaps": false, 43 | "outDir": null 44 | } 45 | ] 46 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | // Place your settings in this file to overwrite default and user settings. 2 | { 3 | // Specifies the folder path containing the tsserver and lib*.d.ts files to use. 4 | "typescript.tsdk": "./node_modules/typescript/lib", 5 | 6 | // Controls the rendering size of tabs in characters. Accepted values: "auto", 2, 4, 6, etc. If set to "auto", the value will be guessed when a file is opened. 7 | "editor.tabSize": 4, 8 | 9 | // Controls if the editor will insert spaces for tabs. Accepted values: "auto", true, false. If set to "auto", the value will be guessed when a file is opened. 10 | "editor.insertSpaces": true, 11 | 12 | "editor.snippetSuggestions": "bottom", 13 | 14 | "files.exclude": { 15 | "**/.git": true, 16 | "**/.DS_Store": true, 17 | "**/*.js": {"when": "$(basename).ts"}, 18 | "**/*.js.map": true, 19 | "*.d.ts": true, 20 | "src/**/*.d.ts": true, 21 | "test/specs/**/*.d.ts": true, 22 | "test/util/**/*.d.ts": true, 23 | "bundles/": true, 24 | "demo-apps/**/build/": true, 25 | "demo-site/api-docs/": true, 26 | "out/": true 27 | } 28 | } -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "0.1.0", 5 | "command": "${cwd}/node_modules/.bin/tsc", 6 | "isShellCommand": true, 7 | "args": [], 8 | "showOutput": "silent", 9 | "problemMatcher": "$tsc" 10 | } -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | CONTRIBUTING 2 | ============ 3 | 4 | 1. Fork the repo and clone locally 5 | 2. In locally cloned repo: `npm install && npm run setup` 6 | * This will the build fro the library and all the demo apps 7 | 3. Prove existing code: 8 | * Run the unit tests: `npm test` 9 | * Run the end-to-end tests (see section below) 10 | 4. Make changes in `src` folder 11 | * **Tip**: use `npm run test:w` to verify your changes on save 12 | 5. Add additional unit tests in `test` folder. These should cover your changes 13 | 6. *Optionally* add end-to-end tests in `e2e` folder 14 | 7. Prove changes: 15 | * Run the unit tests: `npm test` 16 | * Run the end-to-end tests (see section below) 17 | 8. Commit changes: `npm run cm` 18 | - why use **npm** and not **git** to commit? See "Conventional commit message" section below 19 | 9. Push your changes to your fork and submit a pull request 20 | 21 | 22 | ## Running end-to-end tests 23 | 24 | * In one terminal window: `npm run e2e-server` 25 | * In another terminal window: `npm run e2e` 26 | * **Tip**: use `npm run e2e-only` if you already have built source code (ie you've `npm run setup` or `npm run build:all`) 27 | 28 | 29 | ## Conventional commit message 30 | 31 | This project uses the structure of the commit message to: 32 | 33 | 1. Generate release notes like you see in [this release](https://github.com/esvit/ng-table/releases/tag/v2.0.0) 34 | 2. Generate the next version number for the npm package using the rules of [semver](http://semver.org/) 35 | 3. Trigger the publish a release of this library to npm using [semantic-release](https://github.com/semantic-release/semantic-release) 36 | 37 | These conventions are detailed here: [angular commit message conventions](https://github.com/conventional-changelog/conventional-changelog-angular/blob/master/convention.md) 38 | 39 | ### Commitizen command line tool 40 | 41 | To help you to follow these conventions this project uses [Commitizen](https://github.com/commitizen/cz-cli). 42 | 43 | Commitizen provides a command line tool that will help you create a commit message that matches these conventions. 44 | 45 | To lauch this tool we use `npm run cm`. 46 | 47 | 48 | ## Releasing 49 | 50 | See the [releasing](RELEASING.md) guidelines. -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013, esvit. 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 5 | 6 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | Neither the name of the esvit nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 9 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Table + AngularJS 2 | ================= 3 | [![Build Status](https://travis-ci.org/esvit/ng-table.svg)](https://travis-ci.org/esvit/ng-table) [![Coverage Status](https://coveralls.io/repos/esvit/ng-table/badge.png)](https://coveralls.io/r/esvit/ng-table) 4 | [![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release) 5 | 6 | Code licensed under New BSD License. 7 | 8 | This directive enhances your HTML tables. It support sorting, filtering and pagination. 9 | Header row with titles and filters automatic generated. 10 | 11 | 12 | ## Installing 13 | 14 | **NPM** 15 | 16 | Install the current stable release: 17 | ``` 18 | npm install ng-table --save 19 | ``` 20 | Or install the latest beta release: 21 | ``` 22 | npm install ng-table@next --save 23 | ``` 24 | 25 | **note: when to use `next`?** see this [issue-comment](https://github.com/esvit/ng-table/issues/953#issuecomment-270905068) 26 | 27 | **CDN** 28 | 29 | You can download the distribution files directly from [unpkg](https://unpkg.com/ng-table/bundles/) 30 | 31 | **Bower**: NO LONGER SUPPORTED 32 | 33 | 34 | ## Getting started 35 | 36 | Please follow the getting started steps [here](http://ng-table.com/) 37 | 38 | 39 | ## Examples 40 | 41 | * [Demo site](http://ng-table.com/) 42 | * Sample apps: 43 | * [ES5](demo-apps/es5/readme.md) 44 | * [ES2015 + SystemJS](demo-apps/es6-systemjs/readme.md) 45 | * [ES2015 + Webpack](demo-apps/es6-webpack/readme.md) 46 | * [Typescript + Webpack](demo-apps/ts-webpack/readme.md) 47 | * Codepen examples (**Tip**: fork these to create your own examples); 48 | * [`ngTable`: inmemory list](http://codepen.io/christianacca/pen/VLqVeo?editors=101) 49 | * [`ngTable`: server-side list](http://codepen.io/christianacca/pen/VLqqjP?editors=101) 50 | * [`ngTableDynamic`: inmemory list](http://codepen.io/christianacca/pen/jPxgzY?editors=101) 51 | * [`ngTableDynamic`: server-side list](http://codepen.io/christianacca/pen/JdwwrR/?editors=101) 52 | 53 | 54 | ## Using Typescript? 55 | 56 | As of v2.0.0 ngTable is written in typescript and so you do NOT have to install external type declarations for this library. 57 | 58 | By installing the [ng-table package from npm](https://www.npmjs.com/package/ng-table), you will get typescript intellisense for all ng-table exported types. 59 | 60 | **WARNING:**. The type definitions on [DefinitelyTyped](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/ng-table) are depreciated. 61 | 62 | 63 | ## Upgrading from an earlier version? 64 | 65 | ### Upgrade from 0.8.3 66 | 67 | It's recommended to upgrade in two jumps: 68 | 69 | 1. Upgrade to version 1.0.0-beta.9, making any changes to your application code neccessary to work with this version 70 | * EG: `bower install ng-table#1.0.0-beta.9 --save` 71 | 2. Refactor your application to remove any code that depended on depreciated behaviours that where removed in the 1.0.0 release 72 | 3. Install 1.0.0 (should now be a drop in replacement for 1.0.0-beta.9) 73 | * Bower: `bower install ng-table#1.0.0 --save` 74 | * NPM: `npm i ng-table@1.0.0 --save` 75 | 76 | 77 | ### Upgrade from version earlier than 0.8.3 78 | 79 | It's recommended to upgrade in three jumps: 80 | 81 | 1. Upgrade to version 0.8.3, making any changes to your application code neccessary to work with this version 82 | * EG: `bower install ng-table#0.8.3 --save` 83 | 3. Follow the guide above to upgrade from 0.8.3 -> 1.0.0-beta.9 -> 1.0.0 84 | 85 | **Tips** 86 | * Read the notes in [github releases](https://github.com/esvit/ng-table/releases). Each release details the breaking changes and migration guidance 87 | 88 | 89 | ## Compatibility 90 | 91 | For work in IE < 9 need jQuery, just add: 92 | ```html 93 | 96 | ``` 97 | 98 | 99 | ## Building from sources 100 | 101 | 1. Clone: `git clone https://github.com/esvit/ng-table.git` 102 | 2. Install: `npm install` 103 | 3. Build: `npm run build:full` 104 | 105 | * To locally build and serve docs site: `npm run doc && npm run serve:docs-site` 106 | * To locally serve the demo: `npm run serve:demo` 107 | 108 | 109 | ## Want to contribute? 110 | 111 | See the [contributing](CONTRIBUTING.md) guidelines. 112 | 113 | --- 114 | 115 | This project is part of [Bazalt CMS](http://bazalt-cms.com/). 116 | 117 | -------------------------------------------------------------------------------- /RELEASING.md: -------------------------------------------------------------------------------- 1 | RELEASING 2 | ============ 3 | 4 | ## NPM package 5 | 6 | This library uses [semantic-release](https://github.com/semantic-release/semantic-release) 7 | to fully automate publishing library updates to npm. 8 | 9 | All you need to do is ensure you follow the [contributing](CONTRIBUTING.md) guidelines. 10 | 11 | ### NPM dist-tags 12 | 13 | By default this new package version will be published with a [dist-tag](https://docs.npmjs.com/cli/dist-tag#purpose) of `next` 14 | 15 | Implications: 16 | 17 | * To install this version: `npm install ng-table@next --save` 18 | * To make this version available via `npm install ng-table --save`, a dist-tag of `latest` must be manually added (see steps below) 19 | 20 | #### Adding the `latest` dist-tag 21 | 22 | 1. Open a command line 23 | 2. Change directory: `cd path/to/ng-table` 24 | 3. Login: `npm adduser` 25 | 4. Add dist-tag: `npm dist-tag add ng-table@n.n.n latest` 26 | * where `n.n.n` is the version of the package that you now want to make the latest 27 | 5. Remove the pre-release tag from the github release of this version 28 | 29 | 30 | ## Documentation 31 | 32 | To publish updates to the library documentation site: 33 | 34 | 1. `npm run doc` 35 | * this will re-generate the api-Docs 36 | 2. `npm run doc-deploy` 37 | * this will prublish the content of demo-site directory from this repo into the gh-pages branch 38 | -------------------------------------------------------------------------------- /circle.yml: -------------------------------------------------------------------------------- 1 | machine: 2 | node: 3 | version: 6.3.1 4 | 5 | dependencies: 6 | pre: 7 | - npm prune && npm install 8 | - npm run setup:ci && npm run build:demo-apps 9 | cache_directories: 10 | - node_modules 11 | 12 | test: 13 | override: 14 | - npm test -------------------------------------------------------------------------------- /demo-apps/es5/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |

ng-table sample app (ES5)

20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /demo-apps/es5/index.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | 'use strict'; 3 | 4 | angular.module('demo-app', ['ngTable']); 5 | })(); -------------------------------------------------------------------------------- /demo-apps/es5/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ng-table-demo-app-es5", 3 | "version": "1.0.0", 4 | "author": "Vitalii Savchuk ", 5 | "license": "BSD", 6 | "description": "ng-table example app; app written in ECMAScript 5; ng-table added as global script tag", 7 | "private": true, 8 | "scripts": { 9 | "_linklocal": "node ../../node_modules/linklocal/bin/linklocal.js", 10 | "build": "echo \"Nothing to build\"", 11 | "clean": "echo \"Nothing to clean\"", 12 | "linklocal": "npm run _linklocal && npm prune", 13 | "start": "node ../../node_modules/http-server/bin/http-server -c-1 -o", 14 | "unlinklocal": "npm run _linklocal -- unlink && npm i" 15 | }, 16 | "keywords": [], 17 | "dependencies": { 18 | "angular": "file:../../node_modules/angular", 19 | "bootstrap-css-only": "file:../../node_modules/bootstrap-css-only", 20 | "ng-table": "file:../../" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /demo-apps/es5/readme.md: -------------------------------------------------------------------------------- 1 | # ngTable ES5 Demo App 2 | 3 | ## Overview 4 | 5 | * Loads `ng-table` on to the page using a global script tag 6 | * Application code written in ECMAScript 5 7 | 8 | ## Running sample App 9 | 10 | 1. If you haven't already done so: `npm run setup` 11 | 2. `cd demo-apps/es5` (this directory) 12 | 3. `npm start` 13 | * runs `http-server` to serve this app's index.html -------------------------------------------------------------------------------- /demo-apps/es5/src/my-table.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 9 | 10 |
4 | {{user.name}} 5 | 7 | {{user.age}} 8 |
-------------------------------------------------------------------------------- /demo-apps/es5/src/my-table.component.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 'use strict'; 3 | 4 | angular.module('demo-app') 5 | .component('myTable', { 6 | templateUrl: 'src/my-table.component.html', 7 | controller: myTableController 8 | }); 9 | 10 | myTableController.$inject = ['NgTableParams']; 11 | function myTableController(NgTableParams) { 12 | var data = [ 13 | { name: "Moroni", age: 50 }, 14 | { name: "Tiancum", age: 43 }, 15 | { name: "Jacob", age: 27 }, 16 | { name: "Nephi", age: 29 }, 17 | { name: "Enos", age: 34 }, 18 | { name: "Tiancum", age: 43 }, 19 | { name: "Jacob", age: 27 }, 20 | { name: "Nephi", age: 29 }, 21 | { name: "Enos", age: 34 }, 22 | { name: "Tiancum", age: 43 }, 23 | { name: "Jacob", age: 27 }, 24 | { name: "Nephi", age: 29 }, 25 | { name: "Enos", age: 34 }, 26 | { name: "Tiancum", age: 43 }, 27 | { name: "Jacob", age: 27 }, 28 | { name: "Nephi", age: 29 }, 29 | { name: "Enos", age: 34 } 30 | ]; 31 | 32 | this.tableParams = new NgTableParams({}, { 33 | dataset: data 34 | }); 35 | } 36 | 37 | })(); -------------------------------------------------------------------------------- /demo-apps/es6-systemjs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 20 | 21 | 22 | 23 | 24 |

ng-table sample app (ES2015+SystemJS)

25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /demo-apps/es6-systemjs/index.js: -------------------------------------------------------------------------------- 1 | import * as ng from 'angular'; 2 | import { ngTableModule } from 'ng-table'; 3 | import { myTableComponent } from './src/my-table.component'; 4 | 5 | ng.module('demo-app', [ngTableModule.name]) 6 | .component('myTable', myTableComponent); 7 | 8 | ng.element(document).ready(() => { 9 | ng.bootstrap(document, ["demo-app"], { 10 | strictDi: true 11 | }); 12 | }); -------------------------------------------------------------------------------- /demo-apps/es6-systemjs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ng-table-demo-app-es6-systemjs", 3 | "version": "1.0.0", 4 | "author": "Vitalii Savchuk ", 5 | "license": "BSD", 6 | "description": "ng-table example app; app written in es2015; systemjs to load scripts", 7 | "private": true, 8 | "scripts": { 9 | "_linklocal": "node ../../node_modules/linklocal/bin/linklocal.js", 10 | "build": "echo \"Nothing to build\"", 11 | "clean": "echo \"Nothing to clean\"", 12 | "linklocal": "npm run _linklocal && npm prune", 13 | "start": "node ../../node_modules/http-server/bin/http-server -c-1 -o", 14 | "unlinklocal": "npm run _linklocal -- unlink && npm i" 15 | }, 16 | "keywords": [], 17 | "dependencies": { 18 | "angular": "file:../../node_modules/angular", 19 | "bootstrap-css-only": "file:../../node_modules/bootstrap-css-only", 20 | "core-js": "file:../../node_modules/core-js", 21 | "ng-table": "file:../../", 22 | "systemjs": "file:../../node_modules/systemjs", 23 | "systemjs-plugin-babel": "file:../../node_modules/systemjs-plugin-babel" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /demo-apps/es6-systemjs/readme.md: -------------------------------------------------------------------------------- 1 | # ngTable ES6+SystemJS Demo App 2 | 3 | ## Overview 4 | 5 | * Loads `ng-table` on to the page using SystemJS 6 | * Application code written in ES2015 7 | 8 | ## Running sample App 9 | 10 | 1. If you haven't already done so: `npm run setup` 11 | 2. `demo-apps/es6-systemjs` (this directory) 12 | 3. `npm start` 13 | * runs `http-server` to serve this app's index.html -------------------------------------------------------------------------------- /demo-apps/es6-systemjs/src/my-table.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 9 | 10 |
4 | {{user.name}} 5 | 7 | {{user.age}} 8 |
-------------------------------------------------------------------------------- /demo-apps/es6-systemjs/src/my-table.component.js: -------------------------------------------------------------------------------- 1 | import { NgTableParams } from 'ng-table'; 2 | 3 | // note: because of Firefox (v45-v48) native class syntax causes a problem in angular. 4 | // This is not likely going to be fixed in angular as it's a bug in the browser deviating from the spec 5 | // Therefore if you do not want a transpiler step, you will NOT be able to use class syntax 6 | // For more details see: https://github.com/angular/angular.js/issues/14240#issuecomment-197418167 7 | 8 | function MyTableController() { 9 | var data = [ 10 | { name: "Moroni", age: 50 }, 11 | { name: "Tiancum", age: 43 }, 12 | { name: "Jacob", age: 27 }, 13 | { name: "Nephi", age: 29 }, 14 | { name: "Enos", age: 34 }, 15 | { name: "Tiancum", age: 43 }, 16 | { name: "Jacob", age: 27 }, 17 | { name: "Nephi", age: 29 }, 18 | { name: "Enos", age: 34 }, 19 | { name: "Tiancum", age: 43 }, 20 | { name: "Jacob", age: 27 }, 21 | { name: "Nephi", age: 29 }, 22 | { name: "Enos", age: 34 }, 23 | { name: "Tiancum", age: 43 }, 24 | { name: "Jacob", age: 27 }, 25 | { name: "Nephi", age: 29 }, 26 | { name: "Enos", age: 34 } 27 | ]; 28 | 29 | this.tableParams = new NgTableParams({}, { 30 | dataset: data 31 | }); 32 | } 33 | 34 | MyTableController.$inject = []; 35 | 36 | const myTableComponent = { 37 | templateUrl: 'src/my-table.component.html', 38 | controller: MyTableController 39 | }; 40 | 41 | export { myTableComponent }; -------------------------------------------------------------------------------- /demo-apps/es6-systemjs/system.config.js: -------------------------------------------------------------------------------- 1 | (function (/*globals*/) { 2 | 3 | var maps = { 4 | 'angular': 'node_modules/angular', 5 | 'ng-table': 'node_modules/ng-table', 6 | 'plugin-babel': 'node_modules/systemjs-plugin-babel/plugin-babel.js', 7 | 'systemjs-babel-build': 'node_modules/systemjs-plugin-babel/systemjs-babel-browser.js' 8 | }; 9 | 10 | var packages = { 11 | 'ng-table': { main: '/bundles/ng-table.js', defaultExtension: 'js', format: 'amd' }, 12 | 'src': { defaultExtension: 'js' }, 13 | 'angular': { main: 'index.js', defaultExtension: 'js' } 14 | }; 15 | 16 | System.config({ 17 | map: maps, 18 | packages: packages, 19 | transpiler: 'plugin-babel', 20 | meta: { 21 | '*.js': { 22 | babelOptions: { 23 | // although chrome supports es2015 we're running this sample app in Safari so we 24 | // need to transpile code to ecmascript5 25 | es2015: true 26 | } 27 | } 28 | } 29 | }); 30 | })(this); -------------------------------------------------------------------------------- /demo-apps/es6-webpack/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | ["es2015", {"modules": false}], 4 | "es2016", 5 | "stage-2" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /demo-apps/es6-webpack/_debug-webpack.js: -------------------------------------------------------------------------------- 1 | const config = require('./webpack.config.js')(); 2 | console.log(config); -------------------------------------------------------------------------------- /demo-apps/es6-webpack/index.tpl.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Sample app (ES2015+Webpack) | ng-table 10 | <% for (var css in htmlWebpackPlugin.files.css) { %> 11 | 12 | <% } %> 13 | 14 | 15 | 16 |
17 |

ng-table sample app (ES2015+Webpack)

18 | 19 | 20 | 21 | <% for (var chunk in htmlWebpackPlugin.files.chunks) { if (htmlWebpackPlugin.files.chunks[chunk].css.length === 0) {%> 22 | 23 | <% }} %> 24 | 25 | 26 | -------------------------------------------------------------------------------- /demo-apps/es6-webpack/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ng-table-demo-app-es6-webpack", 3 | "version": "1.0.0", 4 | "author": "Vitalii Savchuk ", 5 | "license": "BSD", 6 | "description": "ng-table example app; app written in es2015; webpack to load scripts", 7 | "private": true, 8 | "scripts": { 9 | "_linklocal": "node ../../node_modules/linklocal/bin/linklocal.js", 10 | "prebuild": "npm run clean", 11 | "build": "node ../../node_modules/webpack/bin/webpack.js --env.debug", 12 | "prebuild:prod": "npm run clean", 13 | "build:prod": "node ../../node_modules/webpack/bin/webpack.js --env.prod", 14 | "clean": "node ../../node_modules/shx/lib/cli.js rm -rf build build-stats.json", 15 | "linklocal": "npm run _linklocal && npm prune", 16 | "serve": "node ../../node_modules/http-server/bin/http-server build -c-1 -o", 17 | "start": "node ../../node_modules/webpack-dev-server/bin/webpack-dev-server.js --env.debug --open", 18 | "stats": "node ../../node_modules/webpack/bin/webpack.js --env.prod --profile --json > build-stats.json", 19 | "unlinklocal": "npm run _linklocal -- unlink && npm i", 20 | "validate": "node ../../node_modules/webpack-validator/dist/bin/webpack-validator.js webpack.config.js" 21 | }, 22 | "keywords": [], 23 | "dependencies": { 24 | "angular": "file:../../node_modules/angular", 25 | "bootstrap-css-only": "file:../../node_modules/bootstrap-css-only", 26 | "ng-table": "file:../../" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /demo-apps/es6-webpack/readme.md: -------------------------------------------------------------------------------- 1 | # ngTable ES6+Webpack Demo App 2 | 3 | ## Overview 4 | 5 | * Loads `ng-table` on to the page using webpack 6 | * Application code written in ES2015 and transpiled to ECMAScript 5 7 | 8 | ## Running sample App 9 | 10 | 1. If you haven't already done so: `npm run setup` 11 | 2. `demo-apps/es6-webpack` (this directory) 12 | 3. `npm start` 13 | * runs `webpack-dev-server` to serve this app's index.html -------------------------------------------------------------------------------- /demo-apps/es6-webpack/src/main.js: -------------------------------------------------------------------------------- 1 | import * as ng1 from 'angular'; 2 | import { ngTableModule } from 'ng-table'; 3 | import './shared/site.scss' 4 | import { myTableComponent } from './my-table/my-table.component'; 5 | 6 | ng1.module('demo-app', [ngTableModule.name]) 7 | .component('myTable', myTableComponent); -------------------------------------------------------------------------------- /demo-apps/es6-webpack/src/my-table/my-table.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 9 | 10 |
4 | {{user.name}} 5 | 7 | {{user.age}} 8 |
-------------------------------------------------------------------------------- /demo-apps/es6-webpack/src/my-table/my-table.component.js: -------------------------------------------------------------------------------- 1 | // todo: find out why this causes webpack to create a bundle that throws the error: 2 | // `Cannot redefine property: NgTableParams` 3 | 4 | import { NgTableParams } from 'ng-table'; 5 | 6 | const templateUrl = require('./my-table.component.html'); 7 | 8 | class MyTableController { 9 | constructor() { 10 | var data = [ 11 | { name: "Moroni", age: 50 }, 12 | { name: "Tiancum", age: 43 }, 13 | { name: "Jacob", age: 27 }, 14 | { name: "Nephi", age: 29 }, 15 | { name: "Enos", age: 34 }, 16 | { name: "Tiancum", age: 43 }, 17 | { name: "Jacob", age: 27 }, 18 | { name: "Nephi", age: 29 }, 19 | { name: "Enos", age: 34 }, 20 | { name: "Tiancum", age: 43 }, 21 | { name: "Jacob", age: 27 }, 22 | { name: "Nephi", age: 29 }, 23 | { name: "Enos", age: 34 }, 24 | { name: "Tiancum", age: 43 }, 25 | { name: "Jacob", age: 27 }, 26 | { name: "Nephi", age: 29 }, 27 | { name: "Enos", age: 34 } 28 | ]; 29 | 30 | this.tableParams = new NgTableParams({}, { 31 | dataset: data 32 | }); 33 | } 34 | } 35 | 36 | MyTableController.$inject = []; 37 | 38 | const myTableComponent = { 39 | templateUrl: templateUrl, 40 | controller: MyTableController 41 | }; 42 | 43 | export { myTableComponent }; -------------------------------------------------------------------------------- /demo-apps/es6-webpack/src/shared/images/webpack-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/esvit/ng-table/b6d5d0bfeef923c617081ffe80a0266d7fb4aa33/demo-apps/es6-webpack/src/shared/images/webpack-logo.png -------------------------------------------------------------------------------- /demo-apps/es6-webpack/src/shared/site.scss: -------------------------------------------------------------------------------- 1 | body { 2 | background: url("images/webpack-logo.png") no-repeat bottom right; 3 | } -------------------------------------------------------------------------------- /demo-apps/es6-webpack/src/shared/vendor-styles.scss: -------------------------------------------------------------------------------- 1 | @import '~bootstrap-css-only/css/bootstrap.css'; 2 | @import '~ng-table/src/styles/ng-table.scss' -------------------------------------------------------------------------------- /demo-apps/es6-webpack/webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const merge = require('webpack-merge'); 3 | 4 | module.exports = (env = { prod: false, debug: false, port: 8080, host: 'localhost' }) => { 5 | 6 | const parts = require('../../scripts/webpack/appParts')(__dirname, env); 7 | 8 | const vendorStyles = { 9 | entry: { 10 | 'vendor-styles': path.join(__dirname, 'src', 'shared', 'vendor-styles.scss') 11 | } 12 | }; 13 | return merge( 14 | { 15 | entry: { 16 | main: path.join(__dirname, 'src', 'main.js') 17 | } 18 | }, 19 | parts.asAppBundle(), 20 | parts.extractBundle({ 21 | vendorSelector: parts.isNotAppModuleSelector 22 | }), 23 | vendorStyles, 24 | parts.isDevServer ? parts.sass() : parts.extractSassChunks(vendorStyles.entry), 25 | parts.es6(), 26 | parts.inlineImages(), 27 | parts.inlineHtmlTemplates(), 28 | parts.inlineNgTableHtmlTemplates(), 29 | parts.useHtmlPlugin(), 30 | parts.forEnvironment() 31 | ); 32 | } -------------------------------------------------------------------------------- /demo-apps/ts-webpack/.gitignore: -------------------------------------------------------------------------------- 1 | src/**/*.js 2 | src/**/*.js.map 3 | src/**/*.d.ts 4 | !src/type-declarations/*.d.ts -------------------------------------------------------------------------------- /demo-apps/ts-webpack/_debug-webpack.js: -------------------------------------------------------------------------------- 1 | const config = require('./webpack.config.js')(); 2 | console.log(config); -------------------------------------------------------------------------------- /demo-apps/ts-webpack/index.tpl.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Sample app (Typescript+Webpack) | ng-table 10 | <% for (var css in htmlWebpackPlugin.files.css) { %> 11 | 12 | <% } %> 13 | 14 | 15 | 16 | 17 | 18 | 19 | <% for (var chunk in htmlWebpackPlugin.files.chunks) { if (htmlWebpackPlugin.files.chunks[chunk].css.length === 0) {%> 20 | 21 | <% }} %> 22 | 23 | 24 | -------------------------------------------------------------------------------- /demo-apps/ts-webpack/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ng-table-demo-app-ts-webpack", 3 | "version": "1.0.0", 4 | "author": "Vitalii Savchuk ", 5 | "license": "BSD", 6 | "description": "ng-table example app; app written in typescript; webpack to load scripts", 7 | "private": true, 8 | "scripts": { 9 | "_linklocal": "node ../../node_modules/linklocal/bin/linklocal.js", 10 | "prebuild": "npm run clean", 11 | "build": "node ../../node_modules/webpack/bin/webpack.js --env.debug", 12 | "prebuild:prod": "npm run clean", 13 | "build:prod": "node ../../node_modules/webpack/bin/webpack.js --progress --env.prod", 14 | "clean": "node ../../node_modules/shx/lib/cli.js rm -rf build build-stats.json src/**/*.{js,js.map}", 15 | "linklocal": "npm run _linklocal && npm prune", 16 | "serve": "node ../../node_modules/http-server/bin/http-server build -c-1 -o", 17 | "start": "node ../../node_modules/webpack-dev-server/bin/webpack-dev-server.js --progress --env.debug --open", 18 | "stats": "node ../../node_modules/webpack/bin/webpack.js --env.prod --profile --json > build-stats.json", 19 | "unlinklocal": "npm run _linklocal -- unlink && npm i", 20 | "validate": "node ../../node_modules/webpack-validator/dist/bin/webpack-validator.js webpack.config.js" 21 | }, 22 | "keywords": [], 23 | "dependencies": { 24 | "angular": "file:../../node_modules/angular", 25 | "angular-route": "file:../../node_modules/angular-route", 26 | "bootstrap-css-only": "file:../../node_modules/bootstrap-css-only", 27 | "ng-table": "file:../.." 28 | }, 29 | "devDependencies": {} 30 | } 31 | -------------------------------------------------------------------------------- /demo-apps/ts-webpack/readme.md: -------------------------------------------------------------------------------- 1 | # ngTable Typescript+Webpack Demo App 2 | 3 | ## Overview 4 | 5 | * Loads `ng-table` on to the page using webpack 6 | * Application code written in Typescript and transpiled to ECMAScript 5 7 | 8 | ## Running sample App 9 | 10 | 1. If you haven't already done so: `npm run setup` 11 | 2. `demo-apps/ts-webpack` (this directory) 12 | 3. `npm start` 13 | * runs `webpack-dev-server` to serve this app's index.html -------------------------------------------------------------------------------- /demo-apps/ts-webpack/src/app-routing.module.ts: -------------------------------------------------------------------------------- 1 | import * as ng1 from 'angular'; 2 | import 'angular-route'; 3 | import { IRouteProvider } from '@types/angular-route'; 4 | 5 | const appRoutingModule = ng1.module('demo-app-routing', ['ngRoute']) 6 | .config(defineRoutes); 7 | 8 | defineRoutes.$inject = ['$routeProvider']; 9 | 10 | function defineRoutes($routeProvider: IRouteProvider){ 11 | 12 | $routeProvider.when('/', { template: ''}); 13 | $routeProvider.when('/grouped', { template: ''}) 14 | $routeProvider.when('/column-binding-eg', { template: ''}) 15 | } 16 | 17 | export { appRoutingModule }; -------------------------------------------------------------------------------- /demo-apps/ts-webpack/src/app.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |

ng-table sample app (Typescript+Webpack)

5 |
6 |
7 |
-------------------------------------------------------------------------------- /demo-apps/ts-webpack/src/app.component.ts: -------------------------------------------------------------------------------- 1 | import { IComponentOptions } from 'angular'; 2 | 3 | export class AppComponent implements IComponentOptions { 4 | templateUrl = './app.component.html' 5 | } -------------------------------------------------------------------------------- /demo-apps/ts-webpack/src/column-binding-eg/column-binding-eg.component.ts: -------------------------------------------------------------------------------- 1 | import { IComponentOptions } from 'angular'; 2 | 3 | import { demoData } from '../shared'; 4 | 5 | export class ColumnBindingEgComponent implements IComponentOptions { 6 | controller = ColumnBindingEgController; 7 | templateUrl = './column-binding-eg.html'; 8 | } 9 | class ColumnBindingEgController { 10 | data = demoData; 11 | } -------------------------------------------------------------------------------- /demo-apps/ts-webpack/src/column-binding-eg/column-binding-eg.html: -------------------------------------------------------------------------------- 1 | Column binding example 2 |
3 |
4 | 5 |
6 |
7 | 8 |
9 |
-------------------------------------------------------------------------------- /demo-apps/ts-webpack/src/column-binding-eg/column-binding-eg.module.ts: -------------------------------------------------------------------------------- 1 | import * as ng1 from 'angular'; 2 | import { ngTableModule } from 'ng-table'; 3 | 4 | import { ColumnBindingEgComponent } from './column-binding-eg.component'; 5 | import { DeclarativeTableComponent } from './declarative-table.component'; 6 | import { DynamicTableComponent } from './dynamic-table.component'; 7 | import { ColumnPickerComponent } from './column-picker.component'; 8 | 9 | import './column-binding.scss'; 10 | 11 | export const columnBindingEgModule = ng1.module('column-binding-eg', [ngTableModule.name]) 12 | .component('columnBindingEg', new ColumnBindingEgComponent()) 13 | .component('declarativeTable', new DeclarativeTableComponent()) 14 | .component('dynamicTable', new DynamicTableComponent()) 15 | .component('columnPicker', new ColumnPickerComponent()); -------------------------------------------------------------------------------- /demo-apps/ts-webpack/src/column-binding-eg/column-binding.scss: -------------------------------------------------------------------------------- 1 | column-picker { 2 | display: block; 3 | margin-bottom: 20px; 4 | } -------------------------------------------------------------------------------- /demo-apps/ts-webpack/src/column-binding-eg/column-picker.component.ts: -------------------------------------------------------------------------------- 1 | import { IComponentOptions } from 'angular'; 2 | import { ColumnDef } from 'ng-table'; 3 | 4 | export class ColumnPickerComponent implements IComponentOptions { 5 | templateUrl = './column-picker.html'; 6 | controller = ColumnPickerController; 7 | bindings = { 8 | columns: '<' 9 | } 10 | } 11 | class ColumnPickerController { 12 | columns: ColumnDef[]; 13 | } -------------------------------------------------------------------------------- /demo-apps/ts-webpack/src/column-binding-eg/column-picker.html: -------------------------------------------------------------------------------- 1 |
2 | 5 |
-------------------------------------------------------------------------------- /demo-apps/ts-webpack/src/column-binding-eg/declarative-table.component.ts: -------------------------------------------------------------------------------- 1 | import { IComponentOptions, IComponentController } from 'angular'; 2 | import { ColumnDef, NgTableParams } from 'ng-table'; 3 | import { Person } from '../shared'; 4 | 5 | export class DeclarativeTableComponent implements IComponentOptions { 6 | controller = DeclarativeTableController; 7 | templateUrl = './declarative-table.html'; 8 | bindings = { 9 | data: '<' 10 | }; 11 | } 12 | class DeclarativeTableController implements IComponentController { 13 | exportedColumns: ColumnDef[]; 14 | data: Person[]; 15 | tableParams = new NgTableParams({}); 16 | $onInit(){ 17 | this.tableParams.settings({ dataset: this.data }); 18 | } 19 | } -------------------------------------------------------------------------------- /demo-apps/ts-webpack/src/column-binding-eg/declarative-table.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 10 | 13 | 14 |
5 | {{user.name}} 6 | 8 | {{user.age}} 9 | 11 | {{user.money}} 12 |
-------------------------------------------------------------------------------- /demo-apps/ts-webpack/src/column-binding-eg/dynamic-table..html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 |
{{row[col.field]}}
-------------------------------------------------------------------------------- /demo-apps/ts-webpack/src/column-binding-eg/dynamic-table.component.ts: -------------------------------------------------------------------------------- 1 | import { IComponentOptions, IComponentController } from 'angular'; 2 | import { DynamicTableColDef, NgTableParams } from 'ng-table'; 3 | import { Person } from '../shared'; 4 | 5 | interface ExtendedDynamicTableColDef extends DynamicTableColDef { 6 | field: string; 7 | } 8 | 9 | export class DynamicTableComponent implements IComponentOptions { 10 | controller = DynamicTableController; 11 | templateUrl = './dynamic-table..html'; 12 | bindings = { 13 | data: '<' 14 | }; 15 | } 16 | class DynamicTableController implements IComponentController { 17 | columns: ExtendedDynamicTableColDef[] = [ 18 | { field: 'name', title: 'Name', show: true, filter: { name: 'text' }, sortable: 'name' }, 19 | { field: 'age', title: 'Age', show: true, filter: { age: 'number' }, sortable: 'age' }, 20 | { field: 'money', title: 'Money', show: true, filter: { money: 'number' }, sortable: 'money' } 21 | ]; 22 | data: Person[]; 23 | tableParams = new NgTableParams({}); 24 | $onInit() { 25 | this.tableParams.settings({ dataset: this.data }); 26 | } 27 | } -------------------------------------------------------------------------------- /demo-apps/ts-webpack/src/grouped-table/grouped-table.component.html: -------------------------------------------------------------------------------- 1 | Grouped table 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 15 | 16 | 17 | 20 | 23 | 26 | 29 | 30 |
10 | 11 | 12 | {{ group.value }} 13 | 14 |
18 | {{user.country}} 19 | 21 | {{user.name}} 22 | 24 | {{user.age}} 25 | 27 | {{user.money}} 28 |
-------------------------------------------------------------------------------- /demo-apps/ts-webpack/src/grouped-table/grouped-table.component.ts: -------------------------------------------------------------------------------- 1 | import { IComponentOptions } from 'angular'; 2 | import { NgTableParams } from 'ng-table'; 3 | 4 | import { demoData } from '../shared/demo-data'; 5 | 6 | export class GroupedTableComponent implements IComponentOptions { 7 | controller = GroupedTableController; 8 | templateUrl = './grouped-table.component.html'; 9 | } 10 | class GroupedTableController { 11 | tableParams = new NgTableParams( 12 | { 13 | // initial grouping 14 | group: 'country' 15 | }, { 16 | dataset: demoData 17 | }); 18 | static $inject = ['NgTableParams']; 19 | } 20 | 21 | interface Person { 22 | name: string; 23 | age: number; 24 | money: number; 25 | country: string; 26 | } -------------------------------------------------------------------------------- /demo-apps/ts-webpack/src/main.ts: -------------------------------------------------------------------------------- 1 | import * as ng1 from 'angular'; 2 | import { ngTableModule } from 'ng-table'; 3 | 4 | import { appRoutingModule } from './app-routing.module'; 5 | import { AppComponent } from './app.component'; 6 | import { MyTableComponent } from './my-table/my-table.component'; 7 | import { GroupedTableComponent } from './grouped-table/grouped-table.component'; 8 | import { columnBindingEgModule } from './column-binding-eg/column-binding-eg.module'; 9 | 10 | ng1.module('demo-app', [ngTableModule.name, appRoutingModule.name, columnBindingEgModule.name]) 11 | .component('appRoot', new AppComponent()) 12 | .component('myTable', new MyTableComponent()) 13 | .component('groupedTable', new GroupedTableComponent()); -------------------------------------------------------------------------------- /demo-apps/ts-webpack/src/my-table/my-table.component.html: -------------------------------------------------------------------------------- 1 | Filterable and sortable table 2 | 3 | 4 | 7 | 10 | 11 |
5 | {{user.name}} 6 | 8 | {{user.age}} 9 |
-------------------------------------------------------------------------------- /demo-apps/ts-webpack/src/my-table/my-table.component.ts: -------------------------------------------------------------------------------- 1 | import { IComponentOptions } from 'angular'; 2 | import { NgTableParams } from 'ng-table'; 3 | 4 | import { demoData } from '../shared/demo-data'; 5 | 6 | export class MyTableComponent implements IComponentOptions { 7 | controller = MyTableController; 8 | templateUrl = './my-table.component.html'; 9 | } 10 | class MyTableController { 11 | tableParams = new NgTableParams({}, { 12 | dataset: demoData 13 | }); 14 | } 15 | 16 | interface Person { 17 | name: string; 18 | age: number; 19 | } -------------------------------------------------------------------------------- /demo-apps/ts-webpack/src/shared/demo-data.ts: -------------------------------------------------------------------------------- 1 | export const demoData = [{"name":"Karen","age":45,"money":798,"country":"Czech Republic"},{"name":"Cat","age":49,"money":749,"country":"Czech Republic"},{"name":"Bismark","age":48,"money":672,"country":"Denmark"},{"name":"Markus","age":41,"money":695,"country":"Costa Rica"},{"name":"Anthony","age":45,"money":559,"country":"Japan"},{"name":"Alex","age":55,"money":645,"country":"Czech Republic"},{"name":"Stephane","age":57,"money":662,"country":"Japan"},{"name":"Alex","age":59,"money":523,"country":"American Samoa"},{"name":"Tony","age":56,"money":540,"country":"Canada"},{"name":"Cat","age":57,"money":746,"country":"China"},{"name":"Christian","age":59,"money":572,"country":"Canada"},{"name":"Tony","age":60,"money":649,"country":"Japan"},{"name":"Cat","age":47,"money":675,"country":"Denmark"},{"name":"Stephane","age":50,"money":674,"country":"China"},{"name":"Markus","age":40,"money":549,"country":"Portugal"},{"name":"Anthony","age":53,"money":660,"country":"Bahamas"},{"name":"Stephane","age":54,"money":549,"country":"China"},{"name":"Karen","age":50,"money":611,"country":"American Samoa"},{"name":"Therese","age":53,"money":754,"country":"China"},{"name":"Bismark","age":49,"money":791,"country":"Canada"},{"name":"Daraek","age":56,"money":640,"country":"Costa Rica"},{"name":"Tony","age":43,"money":674,"country":"Canada"},{"name":"Karen","age":47,"money":700,"country":"Portugal"},{"name":"Therese","age":47,"money":718,"country":"Czech Republic"},{"name":"Karen","age":50,"money":655,"country":"Japan"},{"name":"Daraek","age":59,"money":581,"country":"American Samoa"},{"name":"Daraek","age":60,"money":595,"country":"Portugal"},{"name":"Markus","age":44,"money":607,"country":"China"},{"name":"Simon","age":58,"money":728,"country":"Japan"},{"name":"Simon","age":49,"money":655,"country":"Bahamas"}]; -------------------------------------------------------------------------------- /demo-apps/ts-webpack/src/shared/images/webpack-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/esvit/ng-table/b6d5d0bfeef923c617081ffe80a0266d7fb4aa33/demo-apps/ts-webpack/src/shared/images/webpack-logo.png -------------------------------------------------------------------------------- /demo-apps/ts-webpack/src/shared/index.ts: -------------------------------------------------------------------------------- 1 | export { demoData } from './demo-data'; 2 | export { Person } from './person'; -------------------------------------------------------------------------------- /demo-apps/ts-webpack/src/shared/person.ts: -------------------------------------------------------------------------------- 1 | export interface Person { 2 | name: string; 3 | age: number; 4 | } -------------------------------------------------------------------------------- /demo-apps/ts-webpack/src/shared/site.scss: -------------------------------------------------------------------------------- 1 | body { 2 | background: url("images/webpack-logo.png") no-repeat bottom right; 3 | } -------------------------------------------------------------------------------- /demo-apps/ts-webpack/src/shared/vendor-styles.scss: -------------------------------------------------------------------------------- 1 | @import '~bootstrap-css-only/css/bootstrap.css'; 2 | @import '~ng-table/src/styles/ng-table.scss' -------------------------------------------------------------------------------- /demo-apps/ts-webpack/src/type-declarations/angular-route.d.ts: -------------------------------------------------------------------------------- 1 | declare module '@types/angular-route' { 2 | import mod = angular.route; 3 | export = mod; 4 | } -------------------------------------------------------------------------------- /demo-apps/ts-webpack/src/type-declarations/global.d.ts: -------------------------------------------------------------------------------- 1 | // fake the nodejs require function so that we can add 'require' calls for html files; 2 | // these calls to 'require' will then be converted by webpack ngtemplate-loader 3 | // note that I would have prefered to use standard es2015 import for these 4 | // html files but that would have meant using typescript 2 feature of implicit 5 | // ambient modules which in turn would have meant turning off noImplicitAny checks 6 | // which is a VERY bad idea 7 | declare function require(path: string): any; -------------------------------------------------------------------------------- /demo-apps/ts-webpack/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "module": "commonjs", 5 | "moduleResolution": "node", 6 | "sourceMap": true, 7 | "declaration": false, 8 | "emitDecoratorMetadata": true, 9 | "experimentalDecorators": true, 10 | "removeComments": false, 11 | "noEmitOnError": true, // WARNING: NOT WORKING in webpack ie a compiler error still results in bundled JS 12 | "noImplicitAny": true, 13 | "noImplicitReturns": true, 14 | "suppressImplicitAnyIndexErrors": true 15 | }, 16 | "exclude": ["node_modules"], 17 | "awesomeTypescriptLoaderOptions": { 18 | "forkChecker": true, 19 | "useWebpackText": true //Allows loaders to be chained to awesome-typescript-loader. 20 | } 21 | } -------------------------------------------------------------------------------- /demo-apps/ts-webpack/webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const merge = require('webpack-merge'); 3 | 4 | module.exports = (env = { prod: false, debug: false, port: 8080, host: 'localhost' }) => { 5 | 6 | const parts = require('../../scripts/webpack/appParts')(__dirname, env); 7 | 8 | const extactedStyles = { 9 | entry: { 10 | 'vendor-styles': path.join(__dirname, 'src', 'shared', 'vendor-styles.scss'), 11 | 'site-styles': path.join(__dirname, 'src', 'shared', 'site.scss') 12 | } 13 | }; 14 | 15 | return merge( 16 | { 17 | entry: { 18 | main: path.join(__dirname, 'src', 'main.ts') 19 | } 20 | }, 21 | parts.asAppBundle(), 22 | parts.extractBundle({ 23 | vendorSelector: parts.isNotAppModuleSelector 24 | }), 25 | parts.asAppBundle(), 26 | extactedStyles, 27 | parts.isDevServer ? parts.sass() : parts.extractSassChunks(extactedStyles.entry), 28 | parts.typescript(), 29 | parts.inlineImages(), 30 | parts.inlineHtmlTemplates(), 31 | parts.inlineNgTableHtmlTemplates(), 32 | parts.useHtmlPlugin(), 33 | parts.forEnvironment() 34 | ); 35 | } -------------------------------------------------------------------------------- /demo-site/CNAME: -------------------------------------------------------------------------------- 1 | ng-table.com 2 | -------------------------------------------------------------------------------- /demo-site/css/docs.css: -------------------------------------------------------------------------------- 1 | body > .row { 2 | width: 100%; 3 | } 4 | 5 | [ng-view] { 6 | padding: 20px 0; 7 | } 8 | 9 | .row .page-header { 10 | margin-top: 0; 11 | padding: 0; 12 | } 13 | .page-header h1 { 14 | margin: 0; 15 | padding: 5px 0px; 16 | } 17 | 18 | .bs-docs-sidebar.affix { 19 | position: static; 20 | } 21 | @media (min-width: 768px) { 22 | .bs-docs-sidebar { 23 | padding-left: 20px; 24 | } 25 | } 26 | /* First level of nav */ 27 | .bs-docs-sidenav { 28 | margin-top: 20px; 29 | margin-bottom: 20px; 30 | border-left: 2px solid #b94a48; 31 | } 32 | 33 | .bs-docs-sidenav h1 { 34 | margin: 0; 35 | padding: 10px 18px; 36 | font-size: 24px; 37 | } 38 | .bs-docs-sidenav h1 a { 39 | color: #b94a48; 40 | text-decoration: none; 41 | } 42 | 43 | /* All levels of nav */ 44 | .bs-docs-sidebar .nav > li > a { 45 | display: block; 46 | font-size: 13px; 47 | font-weight: 500; 48 | color: #999; 49 | padding: 4px 20px; 50 | } 51 | .bs-docs-sidebar .nav > li > a:hover, 52 | .bs-docs-sidebar .nav > li > a:focus { 53 | padding-left: 19px; 54 | color: #b94a48; 55 | text-decoration: none; 56 | background-color: transparent; 57 | } 58 | .bs-docs-sidebar .nav > .active > a, 59 | .bs-docs-sidebar .nav > .active:hover > a, 60 | .bs-docs-sidebar .nav > .active:focus > a { 61 | padding-left: 18px; 62 | font-weight: bold; 63 | color: #b94a48; 64 | background-color: transparent; 65 | } 66 | 67 | /* Nav: second level (shown on .active) */ 68 | .bs-docs-sidebar .nav .nav { 69 | display: none; /* Hide by default, but at >768px, show it */ 70 | padding-bottom: 10px; 71 | } 72 | .bs-docs-sidebar .nav .nav > li > a { 73 | padding-top: 1px; 74 | padding-bottom: 1px; 75 | padding-left: 30px; 76 | font-size: 12px; 77 | font-weight: normal; 78 | } 79 | .bs-docs-sidebar .nav .nav > li > a:hover, 80 | .bs-docs-sidebar .nav .nav > li > a:focus { 81 | padding-left: 29px; 82 | } 83 | .bs-docs-sidebar .nav .nav > .active > a, 84 | .bs-docs-sidebar .nav .nav > .active:hover > a, 85 | .bs-docs-sidebar .nav .nav > .active:focus > a { 86 | font-weight: 500; 87 | padding-left: 28px; 88 | } 89 | 90 | /* Back to top (hidden on mobile) */ 91 | .back-to-top { 92 | display: none; 93 | margin-top: 10px; 94 | margin-left: 10px; 95 | padding: 4px 10px; 96 | font-size: 12px; 97 | font-weight: 500; 98 | color: #999; 99 | } 100 | .back-to-top:hover { 101 | text-decoration: none; 102 | color: #b94a48; 103 | } 104 | 105 | @media (min-width: 768px) { 106 | .back-to-top { 107 | display: block; 108 | } 109 | } 110 | 111 | /* Show and affix the side nav when space allows it */ 112 | @media (min-width: 992px) { 113 | .bs-docs-sidebar .nav > .active > ul { 114 | display: block; 115 | } 116 | /* Widen the fixed sidebar */ 117 | .bs-docs-sidebar.affix, 118 | .bs-docs-sidebar.affix-bottom { 119 | width: 213px; 120 | } 121 | .bs-docs-sidebar.affix { 122 | position: fixed; /* Undo the static from mobile first approach */ 123 | top: 20px; 124 | } 125 | .bs-docs-sidebar.affix-bottom { 126 | position: absolute; /* Undo the static from mobile first approach */ 127 | } 128 | .bs-docs-sidebar.affix-bottom .bs-docs-sidenav, 129 | .bs-docs-sidebar.affix .bs-docs-sidenav { 130 | margin-top: 0; 131 | margin-bottom: 0; 132 | } 133 | } 134 | @media (min-width: 1200px) { 135 | /* Widen the fixed sidebar again */ 136 | .bs-docs-sidebar.affix-bottom, 137 | .bs-docs-sidebar.affix { 138 | width: 263px; 139 | } 140 | } 141 | 142 | 143 | /* Footer 144 | -------------------------------------------------- */ 145 | 146 | .bs-footer { 147 | padding: 20px 0; 148 | margin-top: 10px; 149 | text-align: center; 150 | border-top: 1px solid #e5e5e5; 151 | } 152 | .bs-footer p { 153 | margin-bottom: 0; 154 | color: #777; 155 | } 156 | .footer-links { 157 | margin: 10px 0; 158 | } 159 | .footer-links li { 160 | display: inline; 161 | padding: 0 2px; 162 | } 163 | .footer-links li:first-child { 164 | padding-left: 0; 165 | } 166 | 167 | 168 | /* Table */ 169 | .variables-matrix { 170 | border:1px solid #ddd; 171 | width:100%; 172 | margin:10px 0; 173 | } 174 | 175 | .variables-matrix td, 176 | .variables-matrix th { 177 | padding:10px; 178 | } 179 | 180 | .variables-matrix td { 181 | border-top:1px solid #eee; 182 | } 183 | 184 | .variables-matrix td + td, 185 | .variables-matrix th + th { 186 | border-left:1px solid #eee; 187 | } 188 | 189 | .variables-matrix tr:nth-child(even) td { 190 | background:#f5f5f5; 191 | } 192 | 193 | .variables-matrix th { 194 | background:#f1f1f1; 195 | } 196 | 197 | /* bootstrap callouts 198 | -------------------------------------------------- */ 199 | .bs-callout { 200 | padding: 20px; 201 | margin: 20px 0; 202 | border: 1px solid #eee; 203 | border-left-width: 5px; 204 | border-radius: 3px; 205 | } 206 | .bs-callout h4 { 207 | margin-top: 0; 208 | margin-bottom: 5px; 209 | } 210 | .bs-callout p:last-child { 211 | margin-bottom: 0; 212 | } 213 | .bs-callout code { 214 | border-radius: 3px; 215 | } 216 | .bs-callout+.bs-callout { 217 | margin-top: -5px; 218 | } 219 | .bs-callout-default { 220 | border-left-color: #777; 221 | } 222 | .bs-callout-default h4 { 223 | color: #777; 224 | } 225 | .bs-callout-success { 226 | border-left-color: #5cb85c; 227 | } 228 | .bs-callout-success h4 { 229 | color: #5cb85c; 230 | } 231 | .bs-callout-danger { 232 | border-left-color: #d9534f; 233 | } 234 | .bs-callout-danger h4 { 235 | color: #d9534f; 236 | } 237 | .bs-callout-warning { 238 | border-left-color: #f0ad4e; 239 | } 240 | .bs-callout-warning h4 { 241 | color: #f0ad4e; 242 | } 243 | .bs-callout-info { 244 | border-left-color: #1b809e; 245 | } 246 | .bs-callout-info h4 { 247 | color: #1b809e; 248 | } 249 | 250 | /* extra callout styles */ 251 | .bs-callout dl { 252 | margin-top: 10px 253 | } 254 | -------------------------------------------------------------------------------- /demo-site/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/esvit/ng-table/b6d5d0bfeef923c617081ffe80a0266d7fb4aa33/demo-site/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /demo-site/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/esvit/ng-table/b6d5d0bfeef923c617081ffe80a0266d7fb4aa33/demo-site/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /demo-site/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/esvit/ng-table/b6d5d0bfeef923c617081ffe80a0266d7fb4aa33/demo-site/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /demo-site/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ngTable Examples 6 | 7 | 8 | 9 | 10 | 11 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | Fork me on GitHub 28 | 29 | 74 |
75 |

Made with love in Ukraine. On any questions or propositions write me a letter esvit666@gmail.com

76 |

Code licensed under New BSD License.

77 | 78 |
    82 | 83 | 84 |
  • Google+
  • 85 |
  • GitHub
  • 86 |
  • Forks
  • 87 |
88 |
89 | 90 | 91 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /demo-site/js/embed-codepen.min.js: -------------------------------------------------------------------------------- 1 | angular.module("embedCodepen.config",[]).value("embedCodepen.config",{debug:!0}),angular.module("embedCodepen.directives",[]),angular.module("embedCodepen",["embedCodepen.config","embedCodepen.directives"]),function(){function e(){return{restrict:"A",scope:{themeId:"@",slugHash:"@",user:"@",defaultTab:"@",height:"@",showTabBar:"@",animations:"@",border:"@",borderColor:"@",tabBarColor:"@",tabLinkColor:"@",activeTabColor:"@",activeLinkColor:"@",linkLogoColor:"@","class":"@",customCssUrl:"@"},template:[""].join(""),link:function(e,o){if(e.slugHash&&e.user){var r=document.location.protocol+"//codepen.io/"+e.user+"/embed/"+e.slugHash+"?user="+e.user,a=["themeId","defaultTab","height","showTabBar","animations","border","borderColor","tabBarColor","tabLinkColor","activeTabColor","activeLinkColor","linkLogoColor","class","customCssUrl"];angular.forEach(a,function(o){e[o]&&(r+="&"+o+"="+e[o])}),o.find("iframe").attr("src",r).attr("height",e.height).attr("id","cp_embed_"+e.slugHash)}}}}e.$inject=[],angular.module("embedCodepen.directives").directive("slugHash",e)}(); -------------------------------------------------------------------------------- /demo-site/js/embed-codepen.version.txt: -------------------------------------------------------------------------------- 1 | 1.1.1 2 | -------------------------------------------------------------------------------- /demo-site/views/columns/demo-reordering.html: -------------------------------------------------------------------------------- 1 |

See the Pen Reordering columns by christianacca (@christianacca) on CodePen.

2 | -------------------------------------------------------------------------------- /demo-site/views/columns/demo-visibility.html: -------------------------------------------------------------------------------- 1 |

See the Pen Showing and hiding columns by christianacca (@christianacca) on CodePen.

2 | -------------------------------------------------------------------------------- /demo-site/views/editing/demo-batch.html: -------------------------------------------------------------------------------- 1 |

See the Pen Batch editable table by christianacca (@christianacca) on CodePen.

2 | -------------------------------------------------------------------------------- /demo-site/views/editing/demo-inline.html: -------------------------------------------------------------------------------- 1 |

See the Pen Inline row editing by christianacca (@christianacca) on CodePen.

2 | -------------------------------------------------------------------------------- /demo-site/views/events/demo-subscribe.html: -------------------------------------------------------------------------------- 1 |

See the Pen Subscribing to NgTableParams events by christianacca (@christianacca) on CodePen.

2 | -------------------------------------------------------------------------------- /demo-site/views/events/demo-unsubscribe.html: -------------------------------------------------------------------------------- 1 |

See the Pen Unsubscribing to NgTableParams events by christianacca (@christianacca) on CodePen.

2 | -------------------------------------------------------------------------------- /demo-site/views/filtering/demo-api.html: -------------------------------------------------------------------------------- 1 |

See the Pen Change filter values programmatically by christianacca (@christianacca) on CodePen.

2 | -------------------------------------------------------------------------------- /demo-site/views/filtering/demo-custom-template.html: -------------------------------------------------------------------------------- 1 |

See the Pen Custom filter template by christianacca (@christianacca) on CodePen.

2 | -------------------------------------------------------------------------------- /demo-site/views/filtering/demo-customize-algorithm.html: -------------------------------------------------------------------------------- 1 |

See the Pen Customize filter algorithm by christianacca (@christianacca) on CodePen.

2 | -------------------------------------------------------------------------------- /demo-site/views/filtering/demo-enabling.html: -------------------------------------------------------------------------------- 1 |

See the Pen Enable filters programmatically by christianacca (@christianacca) on CodePen.

2 | -------------------------------------------------------------------------------- /demo-site/views/filtering/demo-filtering-basic.html: -------------------------------------------------------------------------------- 1 |

See the Pen Filtering - basic example by christianacca (@christianacca) on CodePen.

2 | -------------------------------------------------------------------------------- /demo-site/views/filtering/demo-multi-template.html: -------------------------------------------------------------------------------- 1 |

See the Pen Multi-template filter by christianacca (@christianacca) on CodePen.

2 | -------------------------------------------------------------------------------- /demo-site/views/filtering/demo-nested-property.html: -------------------------------------------------------------------------------- 1 |

See the Pen Nested properties filters by christianacca (@christianacca) on CodePen.

2 | -------------------------------------------------------------------------------- /demo-site/views/filtering/demo-select.html: -------------------------------------------------------------------------------- 1 |

See the Pen Select Filter by christianacca (@christianacca) on CodePen.

2 | -------------------------------------------------------------------------------- /demo-site/views/formatting/demo-cell-values.html: -------------------------------------------------------------------------------- 1 |

See the Pen Data cell template by christianacca (@christianacca) on CodePen.

2 | -------------------------------------------------------------------------------- /demo-site/views/formatting/demo-custom-header.html: -------------------------------------------------------------------------------- 1 |

See the Pen Custom header by christianacca (@christianacca) on CodePen.

2 | -------------------------------------------------------------------------------- /demo-site/views/formatting/demo-dynamic-html-values.html: -------------------------------------------------------------------------------- 1 |

See the Pen Advanced cell value display in ngTableDynamic (via HTML) by christianacca (@christianacca) on CodePen.

2 | -------------------------------------------------------------------------------- /demo-site/views/formatting/demo-dynamic-js-values.html: -------------------------------------------------------------------------------- 1 |

See the Pen Display cell values within ngTableDynamic by christianacca (@christianacca) on CodePen.

2 | -------------------------------------------------------------------------------- /demo-site/views/formatting/demo-header-cell-basic.html: -------------------------------------------------------------------------------- 1 |

See the Pen Header cell template - simple by christianacca (@christianacca) on CodePen.

2 | -------------------------------------------------------------------------------- /demo-site/views/formatting/demo-header-cell-full.html: -------------------------------------------------------------------------------- 1 |

See the Pen Header cell template - full by christianacca (@christianacca) on CodePen.

2 | -------------------------------------------------------------------------------- /demo-site/views/formatting/demo-row.html: -------------------------------------------------------------------------------- 1 |

See the Pen Row template by christianacca (@christianacca) on CodePen.

2 | -------------------------------------------------------------------------------- /demo-site/views/global-customization/demo-defaults.html: -------------------------------------------------------------------------------- 1 |

See the Pen Change default settings and paramater values by christianacca (@christianacca) on CodePen.

2 | -------------------------------------------------------------------------------- /demo-site/views/global-customization/demo-response-interceptors.html: -------------------------------------------------------------------------------- 1 |

See the Pen getData response interceptors by christianacca (@christianacca) on CodePen.

2 | -------------------------------------------------------------------------------- /demo-site/views/grouping/demo-api.html: -------------------------------------------------------------------------------- 1 |

See the Pen Change grouping column programmatically by christianacca (@christianacca) on CodePen.

2 | -------------------------------------------------------------------------------- /demo-site/views/grouping/demo-enabling.html: -------------------------------------------------------------------------------- 1 |

See the Pen Enable grouping programmatically by christianacca (@christianacca) on CodePen.

2 | -------------------------------------------------------------------------------- /demo-site/views/grouping/demo-grouping-basic.html: -------------------------------------------------------------------------------- 1 |

See the Pen Grouping - basic example by christianacca (@christianacca) on CodePen.

2 | -------------------------------------------------------------------------------- /demo-site/views/grouping/demo-grouping-fn.html: -------------------------------------------------------------------------------- 1 |

See the Pen Custom grouping function by christianacca (@christianacca) on CodePen.

2 | -------------------------------------------------------------------------------- /demo-site/views/grouping/demo-summary.html: -------------------------------------------------------------------------------- 1 |

See the Pen Groups with summary row by christianacca (@christianacca) on CodePen.

2 | -------------------------------------------------------------------------------- /demo-site/views/intro/demo-real-world.html: -------------------------------------------------------------------------------- 1 |

See the Pen ngTable - Real world example by christianacca (@christianacca) on CodePen.

2 | -------------------------------------------------------------------------------- /demo-site/views/intro/overview.html: -------------------------------------------------------------------------------- 1 | 7 | 8 |
9 | 10 |
11 |
12 |

Steps for getting started (example on right)

13 |
    14 |
  1. Add references to AngularJS. EG:
    15 |
    16 | <script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.2/angular.js"></script>
    17 | 
    18 |
  2. 19 |
  3. Add references to ngTable's javascript and css files. EG:
    20 |
    21 | <link rel="stylesheet"; href="https://unpkg.com/ng-table@2.0.2/bundles/ng-table.min.css">
    22 | <script src="https://unpkg.com/ng-table@2.0.2/bundles/ng-table.min.js"></script>
    23 | 
    24 |

    25 | Note: ng-table npm package distributes individual ES2015 modules. Use these instead, if your app uses webpack to bundle vendor dependencies 26 |

    27 |
  4. 28 |
  5. Where you declare your app module, add ngTable:
    29 |
    30 | angular.module("myApp", ["ngTable"]);
    31 | 
    32 |
  6. 33 |
  7. In your html file within the controller where you plan to use ng-table, add:
    34 |
    35 | <table ng-table="vm.tableParams" class="table" show-filter="true">
    36 |     <tr ng-repeat="user in $data">
    37 |         <td title="'Name'" filter="{ name: 'text'}" sortable="'name'">
    38 |             {{user.name}}</td>
    39 |         <td title="'Age'" filter="{ age: 'number'}" sortable="'age'">
    40 |             {{user.age}}</td>
    41 |     </tr>
    42 | </table>
    43 | 
    44 |
  8. 45 |
  9. In your javascript file within the controller where you plan to use ng-table, declare:
  10. 46 |
    47 | var self = this;
    48 | var data = [{name: "Moroni", age: 50} /*,*/];
    49 | self.tableParams = new NgTableParams({}, { dataset: data});
    50 | 
    51 |
52 |
53 |
54 |
55 | 56 |

Example

57 |
58 | 59 | 60 | 61 | 64 | 67 | 68 |
62 | {{user.name}} 63 | 65 | {{user.age}} 66 |
69 |
70 | 71 |
72 | 73 |
74 | -------------------------------------------------------------------------------- /demo-site/views/loading/demo-external-array.html: -------------------------------------------------------------------------------- 1 |

See the Pen Loading data - External array by christianacca (@christianacca) on CodePen.

2 | -------------------------------------------------------------------------------- /demo-site/views/loading/demo-lazy-loaded.html: -------------------------------------------------------------------------------- 1 |

See the Pen Loading data - lazy loading managed array by christianacca (@christianacca) on CodePen.

2 | -------------------------------------------------------------------------------- /demo-site/views/loading/demo-managed-array.html: -------------------------------------------------------------------------------- 1 |

See the Pen Loading data - managed array by christianacca (@christianacca) on CodePen.

2 | -------------------------------------------------------------------------------- /demo-site/views/loading/overview.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | 7 | 8 |

There are broadly two options for getting data loaded into a table. These are discussed below

9 | 10 |
11 |
1. Managed array
12 |
13 | Hand NgTableParams an in-memory array and let it do the filtering, sorting and paging 14 | on that array. Eg:
15 |
16 | var dataset = [{ name: 'christian', age: 21 }, { name: 'anthony', age: 88 }];
17 | var tp = new NgTableParams({}, { dataset: dataset });
18 | 
19 |
20 |
2. External array
21 |
22 | Hand NgTableParams a custom getData function that it will call to load 23 | data. Eg:
24 |
25 | var tp = new NgTableParams({}, { getData: function(params){
26 |     /* code to fetch data that matches the params values EG: */
27 |     return executeQuery(params).then(function(data){
28 |         params.total(data.inlineCount);
29 |         return data.results;
30 |     });
31 | }});
32 | 
33 |
34 |
Typically you will use this option to load server-side data
35 |
36 |
37 |
38 | -------------------------------------------------------------------------------- /demo-site/views/pagination/demo-api.html: -------------------------------------------------------------------------------- 1 |

See the Pen Change page / page controls programmatically by christianacca (@christianacca) on CodePen.

2 | -------------------------------------------------------------------------------- /demo-site/views/pagination/demo-pager-basic.html: -------------------------------------------------------------------------------- 1 |

See the Pen Pagination - basic example by christianacca (@christianacca) on CodePen.

2 | -------------------------------------------------------------------------------- /demo-site/views/sorting/demo-api.html: -------------------------------------------------------------------------------- 1 |

See the Pen Change sorting programmatically by christianacca (@christianacca) on CodePen.

2 | -------------------------------------------------------------------------------- /demo-site/views/sorting/demo-enabling.html: -------------------------------------------------------------------------------- 1 |

See the Pen Enable sorting programmatically by christianacca (@christianacca) on CodePen.

2 | -------------------------------------------------------------------------------- /demo-site/views/sorting/demo-sorting-basic.html: -------------------------------------------------------------------------------- 1 |

See the Pen Sorting - basic example by christianacca (@christianacca) on CodePen.

2 | -------------------------------------------------------------------------------- /demo-site/views/todo.html: -------------------------------------------------------------------------------- 1 | 4 | 5 |
6 |

Feel free to contribute a codepen for this missing demo

7 |

Fork this codepen as the base template

8 |

To contribute: create an github issue with a link to your codepen

9 |
10 | -------------------------------------------------------------------------------- /e2e/async-await-example.spec.ts: -------------------------------------------------------------------------------- 1 | import { DemoNgTablePage } from './demo-ng-table.po'; 2 | 3 | describe('async/await', () => { 4 | 5 | it('should be supported in tests', async () => { 6 | const demoPage = new DemoNgTablePage('es5/index.html'); 7 | demoPage.open(); 8 | 9 | if (await demoPage.dataRows.count() === 0){ 10 | expect(true).toBe(false); 11 | } 12 | }); 13 | }); -------------------------------------------------------------------------------- /e2e/builds.spec.ts: -------------------------------------------------------------------------------- 1 | import { DemoNgTablePage } from './demo-ng-table.po'; 2 | 3 | describe('ng-table builds', () => { 4 | 5 | describe('es5', () => { 6 | const demoPageUrl = 'es5/index.html'; 7 | it('should render ng-table', () => { 8 | renderTableSpec(demoPageUrl); 9 | }); 10 | }); 11 | 12 | describe('es6-systemjs', () => { 13 | // demo-app/es6-systemjs is failing in IE less than vs 11 14 | // this seems to be something to do with SystemJS rather than ng-table per sa; 15 | // I given up trying to investigate for lack of time. Degugging the error 16 | // on SauceLabs shows the following error logged to the browser console: 17 | // "Unable to get property 'pos' of undefined or null reference" 18 | if (capabilities.browserName === "internet explorer" && capabilities.version < 11) { 19 | return 20 | } 21 | 22 | const demoPageUrl = 'es6-systemjs/index.html'; 23 | it('should render ng-table', () => { 24 | renderTableSpec(demoPageUrl); 25 | }); 26 | }); 27 | 28 | describe('es6-webpack', () => { 29 | const demoPageUrl = 'es6-webpack/build/index.html'; 30 | it('should render ng-table', () => { 31 | renderTableSpec(demoPageUrl); 32 | }); 33 | }); 34 | 35 | describe('ts-webpack', () => { 36 | const demoPageUrl = 'ts-webpack/build/index.html'; 37 | it('should render ng-table', () => { 38 | renderTableSpec(demoPageUrl); 39 | }); 40 | }); 41 | 42 | 43 | function renderTableSpec(url: string) { 44 | const demoPage = new DemoNgTablePage(url); 45 | demoPage.open(); 46 | expect(demoPage.table.isPresent()).toBe(true); 47 | expect(demoPage.dataRows.count()).toBeGreaterThan(0); 48 | } 49 | }); -------------------------------------------------------------------------------- /e2e/demo-ng-table.po.ts: -------------------------------------------------------------------------------- 1 | import { browser, by, element, ElementArrayFinder, ElementFinder } from 'protractor'; 2 | 3 | export class DemoNgTablePage { 4 | dataRows: ElementArrayFinder; 5 | table: ElementFinder; 6 | constructor(private url: string) { 7 | this.table = element(by.css('table[ng-table]')); 8 | this.dataRows = element.all(by.repeater('user in $data')); 9 | } 10 | open() { 11 | browser.get(this.url); 12 | } 13 | } -------------------------------------------------------------------------------- /e2e/global.d.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | declare var capabilities: { 4 | browserName?: "chrome" | "firefox" | "internet explorer" | "safari"; 5 | /** 6 | * Name of the capability 7 | */ 8 | name?: string; 9 | /** 10 | * Name of the operating system running the process 11 | */ 12 | platform?: string; 13 | /** 14 | * Browser version 15 | */ 16 | version?: number; 17 | }; -------------------------------------------------------------------------------- /e2e/protractor-travis.config.js: -------------------------------------------------------------------------------- 1 | var SpecReporter = require('jasmine-spec-reporter'); 2 | 3 | exports.config = { 4 | 5 | allScriptsTimeout: 30000, 6 | getPageTimeout: 30000, 7 | 8 | specs: [ 9 | '*.spec.ts' 10 | ], 11 | 12 | multiCapabilities: [ 13 | capabilitiesForSauceLabs({ 14 | 'name': 'Linux/Chrome', 15 | 'browserName': 'chrome' 16 | }), 17 | capabilitiesForSauceLabs({ 18 | 'name': 'Linux/Firefox', 19 | 'browserName': 'firefox' 20 | }), 21 | capabilitiesForSauceLabs({ 22 | 'name': 'Win7/Firefox', 23 | 'browserName': 'firefox', 24 | 'platform': 'Windows 7' 25 | }), 26 | capabilitiesForSauceLabs({ 27 | 'name': 'Win7/Chrome', 28 | 'browserName': 'chrome', 29 | 'platform': 'Windows 7' 30 | }) 31 | , 32 | capabilitiesForSauceLabs({ 33 | 'name': 'Win7/IE9', 34 | 'browserName': 'internet explorer', 35 | 'platform': 'Windows 7', 36 | 'version': 9 37 | }), 38 | capabilitiesForSauceLabs({ 39 | 'name': 'Win8/IE10', 40 | 'browserName': 'internet explorer', 41 | 'platform': 'Windows 8', 42 | 'version': 10 43 | }), 44 | capabilitiesForSauceLabs({ 45 | 'name': 'Win8.1/IE11', 46 | 'browserName': 'internet explorer', 47 | 'platform': 'Windows 8.1', 48 | 'version': 11 49 | }), 50 | // capabilitiesForSauceLabs({ 51 | // 'name': 'Win10/Edge', 52 | // 'browserName': 'edge', 53 | // 'platform': 'Windows 10', 54 | // 'version': '13.10586' 55 | // }), 56 | capabilitiesForSauceLabs({ 57 | 'name': 'Mac/Safari 8', 58 | 'browserName': 'safari', 59 | 'platform': 'OS X 10.10', 60 | 'version': 8 61 | }), 62 | capabilitiesForSauceLabs({ 63 | 'name': 'Mac/Safari 9', 64 | 'browserName': 'safari', 65 | 'platform': 'OS X 10.11', 66 | 'version': 9 67 | }) 68 | ], 69 | 70 | baseUrl: 'http://localhost:8080/', 71 | 72 | framework: 'jasmine', 73 | 74 | jasmineNodeOpts: { 75 | defaultTimeoutInterval: 30000, 76 | showColors: true, 77 | includeStackTrace: true 78 | }, 79 | 80 | onPrepare: function () { 81 | jasmine.getEnv().addReporter(new SpecReporter()); 82 | require('ts-node').register({ 83 | project: 'e2e' 84 | }); 85 | return browser.getProcessedConfig().then(function (config) { 86 | global.capabilities = config.capabilities; 87 | }); 88 | }, 89 | 90 | sauceUser: process.env.SAUCE_USERNAME, 91 | sauceKey: process.env.SAUCE_ACCESS_KEY 92 | }; 93 | 94 | function capabilitiesForSauceLabs(capabilities) { 95 | return { 96 | 'tunnel-identifier': process.env.TRAVIS_JOB_NUMBER, 97 | 98 | 'name': capabilities.name, 99 | 'build': process.env.TRAVIS_BUILD_NUMBER, 100 | 101 | 'browserName': capabilities.browserName, 102 | 'platform': capabilities.platform, 103 | 'version': capabilities.version 104 | }; 105 | } -------------------------------------------------------------------------------- /e2e/protractor.config.js: -------------------------------------------------------------------------------- 1 | var HtmlScreenshotReporter = require('protractor-jasmine2-screenshot-reporter'); 2 | 3 | var reporter = new HtmlScreenshotReporter({ 4 | cleanDestination: true, 5 | dest: './out/test/end2end/reports', 6 | filename: 'e2e.html', 7 | ignoreSkippedSpecs: true, 8 | showSummary: true, 9 | 10 | // reportOnlyFailedSpecs: true, 11 | // captureOnlyFailedSpecs: true 12 | }); 13 | 14 | exports.config = { 15 | 16 | allScriptsTimeout: 11000, 17 | 18 | specs: [ 19 | '*.spec.ts' 20 | ], 21 | 22 | capabilities: { 23 | 'browserName': 'chrome' 24 | }, 25 | 26 | baseUrl: 'http://localhost:8080/', 27 | 28 | framework: 'jasmine', 29 | 30 | jasmineNodeOpts: { 31 | defaultTimeoutInterval: 30000, 32 | showColors: true, 33 | includeStackTrace: true 34 | }, 35 | 36 | beforeLaunch: function () { 37 | require('ts-node').register({ 38 | project: 'e2e' 39 | }); 40 | // Setup the report before any tests start 41 | return new Promise(function (resolve) { 42 | reporter.beforeLaunch(resolve); 43 | }); 44 | }, 45 | 46 | onPrepare: function () { 47 | jasmine.getEnv().addReporter(reporter); 48 | 49 | return browser.getProcessedConfig().then(function (config) { 50 | global.capabilities = config.capabilities; 51 | }); 52 | }, 53 | 54 | afterLaunch: function (exitCode) { 55 | // Close the report after all tests finish 56 | return new Promise(function (resolve) { 57 | reporter.afterLaunch(resolve.bind(this, exitCode)); 58 | }); 59 | } 60 | }; -------------------------------------------------------------------------------- /e2e/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2015", 4 | "module": "commonjs", 5 | "moduleResolution": "node", 6 | "sourceMap": false, 7 | "declaration": false, 8 | "emitDecoratorMetadata": true, 9 | "experimentalDecorators": true, 10 | "noImplicitAny": true, 11 | "noImplicitReturns": true, 12 | "suppressImplicitAnyIndexErrors": true, 13 | "typeRoots": [ 14 | "../node_modules/@types" 15 | ] 16 | }, 17 | "include": [ 18 | "./**/*" 19 | ], 20 | "exclude": [ 21 | "node_modules" 22 | ] 23 | } -------------------------------------------------------------------------------- /examples-old/app/app.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'angular', 3 | 'ngTable' 4 | ], function (angular) { 5 | 'use strict'; 6 | 7 | var app = angular.module('main', ['ngTable']). 8 | controller('DemoCtrl', function($scope, $filter, $q, NgTableParams) { 9 | var data = [{name: "Moroni", age: 50, money: -10}, 10 | {name: "Tiancum", age: 43,money: 120}, 11 | {name: "Jacob", age: 27, money: 5.5}, 12 | {name: "Nephi", age: 29,money: -54}, 13 | {name: "Enos", age: 34,money: 110}, 14 | {name: "Tiancum", age: 43, money: 1000}, 15 | {name: "Jacob", age: 27,money: -201}, 16 | {name: "Nephi", age: 29, money: 100}, 17 | {name: "Enos", age: 34, money: -52.5}, 18 | {name: "Tiancum", age: 43, money: 52.1}, 19 | {name: "Jacob", age: 27, money: 110}, 20 | {name: "Nephi", age: 29, money: -55}, 21 | {name: "Enos", age: 34, money: 551}, 22 | {name: "Tiancum", age: 43, money: -1410}, 23 | {name: "Jacob", age: 27, money: 410}, 24 | {name: "Nephi", age: 29, money: 100}, 25 | {name: "Enos", age: 34, money: -100}]; 26 | 27 | $scope.tableParams = new NgTableParams({ 28 | $liveFiltering: true, 29 | page: 1, // show first page 30 | total: data.length, // length of data 31 | count: 10 // count per page 32 | }); 33 | 34 | $scope.names = function(column) { 35 | var def = $q.defer(), 36 | arr = [], 37 | names = []; 38 | angular.forEach(data, function(item){ 39 | if ($.inArray(item.name, arr) === -1) { 40 | arr.push(item.name); 41 | names.push({ 42 | 'id': item.name, 43 | 'title': item.name 44 | }); 45 | } 46 | }); 47 | def.resolve(names); 48 | return def.promise; 49 | }; 50 | 51 | $scope.$watch('tableParams', function(params) { 52 | // use built-in angular filter 53 | var orderedData = params.sorting ? 54 | $filter('orderBy')(data, params.orderBy()) : 55 | data; 56 | orderedData = params.filter ? 57 | $filter('filter')(orderedData, params.filter) : 58 | orderedData; 59 | 60 | params.total = orderedData.length; // set total for recalc pagination 61 | $scope.users = orderedData.slice((params.page - 1) * params.count, params.page * params.count); 62 | }, true); 63 | }); 64 | return app; 65 | }); 66 | -------------------------------------------------------------------------------- /examples-old/app/main.js: -------------------------------------------------------------------------------- 1 | require.config({ 2 | paths: { 3 | jquery: '../js/jquery-1.9.1.min', 4 | angular: '../js/angular.min', 5 | ngTable: '../../dist' 6 | }, 7 | shim: { 8 | 'angular': {'exports': 'angular'} 9 | } 10 | }); 11 | 12 | require([ 13 | 'jquery', 14 | 'angular', 15 | 'app' 16 | ], function ($, angular, app) { 17 | 'use strict'; 18 | 19 | angular.bootstrap(document, ['main']); 20 | }); 21 | -------------------------------------------------------------------------------- /examples-old/demo15.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 18 | 19 | 20 | 21 | 22 |

Export to CSV

23 | 24 |
25 | 26 | Export to CSV 27 | 28 |
29 | 32 |
33 | 34 | 35 | 36 | 39 | 42 | 43 |
37 | {{user.name}} 38 | 40 | {{user.age}} 41 |
44 | 45 | 73 | 74 |
75 | 76 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /examples-old/demo26.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 |

Table with Resizable Columns

26 | 27 |
28 | 29 | 30 | 31 | 34 | 37 | 38 |
32 | {{user.name}} 33 | 35 | {{user.age}} 36 |
39 | 40 | 84 | 85 | 101 | 102 |
103 | 104 | 105 | 106 | 107 | -------------------------------------------------------------------------------- /examples-old/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/esvit/ng-table/b6d5d0bfeef923c617081ffe80a0266d7fb4aa33/examples-old/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /examples-old/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/esvit/ng-table/b6d5d0bfeef923c617081ffe80a0266d7fb4aa33/examples-old/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /examples-old/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/esvit/ng-table/b6d5d0bfeef923c617081ffe80a0266d7fb4aa33/examples-old/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /examples-old/js/angular-resource.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | AngularJS v1.2.0-rc.2 3 | (c) 2010-2012 Google, Inc. http://angularjs.org 4 | License: MIT 5 | */ 6 | (function(H,g,C){'use strict';var A=g.$$minErr("$resource");g.module("ngResource",["ng"]).factory("$resource",["$http","$parse","$q",function(D,y,E){function n(g,h){this.template=g;this.defaults=h||{};this.urlParams={}}function u(l,h,d){function p(c,b){var e={};b=v({},h,b);q(b,function(a,b){t(a)&&(a=a());var m;a&&a.charAt&&"@"==a.charAt(0)?(m=a.substr(1),m=y(m)(c)):m=a;e[b]=m});return e}function b(c){return c.resource}function e(c){z(c||{},this)}var F=new n(l);d=v({},G,d);q(d,function(c,f){var h= 7 | /^(POST|PUT|PATCH)$/i.test(c.method);e[f]=function(a,f,m,l){var d={},r,s,w;switch(arguments.length){case 4:w=l,s=m;case 3:case 2:if(t(f)){if(t(a)){s=a;w=f;break}s=f;w=m}else{d=a;r=f;s=m;break}case 1:t(a)?s=a:h?r=a:d=a;break;case 0:break;default:throw A("badargs",arguments.length);}var n=r instanceof e,k=n?r:c.isArray?[]:new e(r),x={},u=c.interceptor&&c.interceptor.response||b,y=c.interceptor&&c.interceptor.responseError||C;q(c,function(a,c){"params"!=c&&("isArray"!=c&&"interceptor"!=c)&&(x[c]=z(a))}); 8 | x.data=r;F.setUrlParams(x,v({},p(r,c.params||{}),d),c.url);d=D(x).then(function(a){var b=a.data,f=k.$promise;if(b){if(g.isArray(b)!=!!c.isArray)throw A("badcfg",c.isArray?"array":"object",g.isArray(b)?"array":"object");c.isArray?(k.length=0,q(b,function(a){k.push(new e(a))})):(z(b,k),k.$promise=f)}k.$resolved=!0;(s||B)(k,a.headers);a.resource=k;return a},function(a){k.$resolved=!0;(w||B)(a);return E.reject(a)}).then(u,y);return n?d:(k.$promise=d,k.$resolved=!1,k)};e.prototype["$"+f]=function(a,c, 9 | b){t(a)&&(b=c,c=a,a={});a=e[f](a,this,c,b);return a.$promise||a}});e.bind=function(c){return u(l,v({},h,c),d)};return e}var G={get:{method:"GET"},save:{method:"POST"},query:{method:"GET",isArray:!0},remove:{method:"DELETE"},"delete":{method:"DELETE"}},B=g.noop,q=g.forEach,v=g.extend,z=g.copy,t=g.isFunction;n.prototype={setUrlParams:function(l,h,d){var p=this,b=d||p.template,e,n,c=p.urlParams={};q(b.split(/\W/),function(f){!/^\d+$/.test(f)&&(f&&RegExp("(^|[^\\\\]):"+f+"(\\W|$)").test(b))&&(c[f]=!0)}); 10 | b=b.replace(/\\:/g,":");h=h||{};q(p.urlParams,function(c,d){e=h.hasOwnProperty(d)?h[d]:p.defaults[d];g.isDefined(e)&&null!==e?(n=encodeURIComponent(e).replace(/%40/gi,"@").replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%20/g,"%20").replace(/%26/gi,"&").replace(/%3D/gi,"=").replace(/%2B/gi,"+"),b=b.replace(RegExp(":"+d+"(\\W|$)","g"),n+"$1")):b=b.replace(RegExp("(/?):"+d+"(\\W|$)","g"),function(a,c,b){return"/"==b.charAt(0)?b:c+b})});b=b.replace(/\/+$/,"");b=b.replace(/\/\.(?=\w+($|\?))/, 11 | ".");l.url=b.replace(/\/\\\./,"/.");q(h,function(c,b){p.urlParams[b]||(l.params=l.params||{},l.params[b]=c)})}};return u}])})(window,window.angular); 12 | /* 13 | //@ sourceMappingURL=angular-resource.min.js.map 14 | */ -------------------------------------------------------------------------------- /examples-old/js/ng-table-export.src.js: -------------------------------------------------------------------------------- 1 | angular.module('ngTableExport', []) 2 | .config(['$compileProvider', function($compileProvider) { 3 | // allow data links 4 | $compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|ftp|mailto|data):/); 5 | }]) 6 | .directive('exportCsv', ['$parse', function ($parse) { 7 | return { 8 | restrict: 'A', 9 | scope: false, 10 | link: function(scope, element, attrs) { 11 | var data = ''; 12 | var csv = { 13 | stringify: function(str) { 14 | return '"' + 15 | str.replace(/^\s\s*/, '').replace(/\s*\s$/, '') // trim spaces 16 | .replace(/"/g,'""') + // replace quotes with double quotes 17 | '"'; 18 | }, 19 | generate: function() { 20 | data = ''; 21 | var rows = element.find('tr'); 22 | angular.forEach(rows, function(row, i) { 23 | var tr = angular.element(row), 24 | tds = tr.find('th'), 25 | rowData = ''; 26 | if (tr.hasClass('ng-table-filters')) { 27 | return; 28 | } 29 | if (tds.length == 0) { 30 | tds = tr.find('td'); 31 | } 32 | if (i != 1) { 33 | angular.forEach(tds, function(td, i) { 34 | rowData += csv.stringify(angular.element(td).text()) + ';'; 35 | }); 36 | rowData = rowData.slice(0, rowData.length - 1); //remove last semicolon 37 | } 38 | data += rowData + "\n"; 39 | }); 40 | }, 41 | link: function() { 42 | return 'data:text/csv;charset=UTF-8,' + encodeURIComponent(data); 43 | } 44 | }; 45 | $parse(attrs.exportCsv).assign(scope.$parent, csv); 46 | } 47 | }; 48 | }]); -------------------------------------------------------------------------------- /examples-old/js/ng-table-resizable-columns.js: -------------------------------------------------------------------------------- 1 | /*! ngTableColumnResizable v0.1.0 by Vitalii Savchuk(esvit666@gmail.com) - https://github.com/esvit/ng-table-resizable-columns - New BSD License */ 2 | 3 | angular.module("ngTableResizableColumns",[]).directive("ngTableResizableColumns",function(){function a(a){var b=function(a,b){return function(){return a.apply(b,arguments)}};this.pointerdown=b(this.pointerdown,this);var c=this;this.options={store:window.store,rigidSizing:!1,resizeFromBody:!0},this.$table=a,this.setHeaders(),this.restoreColumnWidths(),this.syncHandleWidths(),$(window).on("resize.rc",function(){return c.syncHandleWidths()})}var b=function(a){return parseFloat(a.style.width.replace("%",""))},c=function(a,b){return a.style.width=""+b.toFixed(2)+"%"},d=function(a){return 0===a.type.indexOf("touch")?(a.originalEvent.touches[0]||a.originalEvent.changedTouches[0]).pageX:a.pageX};return a.prototype.getColumnId=function(a){return this.$table.data("resizable-columns-id")+"-"+a.data("resizable-column-id")},a.prototype.setHeaders=function(){return this.$tableHeaders=this.$table.find("thead tr:first th:visible"),this.assignPercentageWidths(),this.createHandles()},a.prototype.destroy=function(){return this.$handleContainer.remove(),this.$table.removeData("resizableColumns"),$(window).off(".rc")},a.prototype.assignPercentageWidths=function(){var a=this;return this.$tableHeaders.each(function(b,d){var e;return e=$(d),c(e[0],e.outerWidth()/a.$table.width()*100)})},a.prototype.createHandles=function(){var a,b=this;return null!=(a=this.$handleContainer)&&a.remove(),this.$table.before(this.$handleContainer=$("
")),this.$tableHeaders.each(function(a,c){var d;if(0!==b.$tableHeaders.eq(a+1).length&&null==b.$tableHeaders.eq(a).attr("data-noresize")&&null==b.$tableHeaders.eq(a+1).attr("data-noresize"))return d=$("
"),d.data("th",$(c)),d.appendTo(b.$handleContainer)}),this.$handleContainer.on("mousedown touchstart",".rc-handle",this.pointerdown)},a.prototype.syncHandleWidths=function(){var a=this;return this.setHeaders(),this.$handleContainer.width(this.$table.width()).find(".rc-handle").each(function(b,c){var d;return d=$(c),d.css({left:d.data("th").outerWidth()+(d.data("th").offset().left-a.$handleContainer.offset().left),height:a.options.resizeFromBody?a.$table.height():a.$table.find("thead").height()})})},a.prototype.saveColumnWidths=function(){var a=this;return this.$tableHeaders.each(function(c,d){var e;return e=$(d),null==e.attr("data-noresize")&&null!=a.options.store?a.options.store.set(a.getColumnId(e),b(e[0])):void 0})},a.prototype.restoreColumnWidths=function(){var a=this;return this.$tableHeaders.each(function(b,d){var e,f;return e=$(d),null!=a.options.store&&(f=a.options.store.get(a.getColumnId(e)))?c(e[0],f):void 0})},a.prototype.totalColumnWidths=function(){var a;return a=0,this.$tableHeaders.each(function(b,c){return a+=parseFloat($(c)[0].style.width.replace("%",""))}),a},a.prototype.pointerdown=function(a){var e,f,g,h,i,j=this;return a.preventDefault(),h=d(a),e=$(a.currentTarget),f=e.data("th"),g=this.$tableHeaders.eq(this.$tableHeaders.index(f)+1),i={left:b(f[0]),right:b(g[0])},this.$table.addClass("rc-table-resizing"),$(document).on("mousemove.rc touchmove.rc",function(a){var b;return b=(d(a)-h)/j.$table.width()*100,c(g[0],i.right-b),c(f[0],i.left+b)}),$(document).one("mouseup touchend",function(){return $(document).off("mousemove.rc touchmove.rc"),j.$table.removeClass("rc-table-resizing"),j.syncHandleWidths(),j.saveColumnWidths()})},{restrict:"C",priority:999,require:"ngTable",link:function(b,c){var d;b.$watch("$data",function(){d.destroy(),d=new a(c)}),d=new a(c)}}}); 4 | //# sourceMappingURL=ng-table-resizable-columns.map -------------------------------------------------------------------------------- /index.ts: -------------------------------------------------------------------------------- 1 | import * as ng1 from 'angular'; 2 | import { ngTableCoreModule } from './src/core'; 3 | import { ngTableBrowserModule } from './src/browser'; 4 | 5 | const ngTableModule = ng1.module('ngTable', [ngTableCoreModule.name, ngTableBrowserModule.name]); 6 | 7 | export { ngTableModule }; 8 | export * from './src/core'; 9 | export * from './src/browser'; -------------------------------------------------------------------------------- /jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=759670 3 | // for the documentation about the jsconfig.json format 4 | "compilerOptions": { 5 | "target": "es5", 6 | "module": "commonjs", 7 | "allowSyntheticDefaultImports": true 8 | }, 9 | "exclude": [ 10 | "node_modules", 11 | "tmp", 12 | "temp" 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration file 2 | // See http://karma-runner.github.io/0.10/config/configuration-file.html 3 | const testGlob = 'test/index.js'; 4 | var debug = process.env.npm_lifecycle_event === 'test:debug' 5 | const webpackConfig = require('./webpack.config')({ test: true, noCoverage: debug }); 6 | 7 | module.exports = function (config) { 8 | let reporters = ['jasmine-diff', 'dots', 'spec']; 9 | if (!debug) { 10 | reporters.push('coverage'); 11 | } 12 | config.set({ 13 | basePath: '', 14 | 15 | frameworks: ['jasmine'], 16 | 17 | // list of files / patterns to load in the browser 18 | files: [ 19 | // libraries 20 | 'node_modules/lodash/lodash.js', 21 | 'node_modules/angular/angular.js', 22 | 'node_modules/angular-mocks/angular-mocks.js', 23 | testGlob 24 | ], 25 | 26 | // generate js files from html templates 27 | preprocessors: { 28 | [testGlob]: ['webpack'] 29 | }, 30 | webpack: webpackConfig, 31 | webpackMiddleware: { 32 | stats: { 33 | chunks: false, 34 | chunkModules: false, 35 | colors: true, 36 | hash: false 37 | } 38 | }, 39 | reporters: reporters, 40 | colors: true, 41 | logLevel: config.LOG_INFO, 42 | autoWatch: false, 43 | singleRun: true, 44 | browsers: [debug ? 'Chrome' : 'PhantomJS'], 45 | coverageReporter: { 46 | reporters: [ 47 | { type: 'lcov', dir: 'out/coverage' }, 48 | { type: 'cobertura', dir: 'out/coverage' }, 49 | { type: 'json', dir: 'out/coverage' }, 50 | { type: 'text-summary' } 51 | ] 52 | } 53 | }); 54 | }; 55 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ng-table", 3 | "version": "0.0.0-semantic-release", 4 | "author": "Vitalii Savchuk ", 5 | "license": "BSD", 6 | "repository": { 7 | "type": "git", 8 | "url": "git://github.com/esvit/ng-table.git" 9 | }, 10 | "main": "bundles/ng-table.js", 11 | "module": "index.js", 12 | "typings": "index.d.ts", 13 | "release": { 14 | "branch": "master", 15 | "fallbackTags": { 16 | "next": "latest" 17 | } 18 | }, 19 | "publishConfig": { 20 | "tag": "next" 21 | }, 22 | "devDependencies": { 23 | "@types/angular-mocks": "^1.5.4", 24 | "@types/angular-route": "^1.3.2", 25 | "@types/jasmine": "^2.2.33", 26 | "@types/karma-jasmine": "0.0.28", 27 | "@types/lodash": "^4.14.43", 28 | "angular": "^1.5.8", 29 | "angular-mocks": "^1.5.8", 30 | "angular-route": "^1.5.8", 31 | "angular1-template-loader": "^0.1.0", 32 | "awesome-typescript-loader": "^3.0.0-beta.9", 33 | "babel-core": "^6.14.0", 34 | "babel-loader": "^6.2.10", 35 | "babel-preset-es2015": "^6.13.2", 36 | "babel-preset-es2016": "^6.11.3", 37 | "babel-preset-stage-2": "^6.13.0", 38 | "bootstrap-css-only": "^3.3.6", 39 | "bulk": "git+https://github.com/kumarharsh/bulk.git#68ac8daa57191f7ea79279b22b0876cf4ab19575", 40 | "commitizen": "^2.8.6", 41 | "core-js": "^2.4.1", 42 | "coveralls": "~2.11.0", 43 | "css-loader": "^0.23.1", 44 | "cz-conventional-changelog": "^1.2.0", 45 | "extract-text-webpack-plugin": "^2.0.0-beta.3", 46 | "file-loader": "^0.9.0", 47 | "gh-pages": "^0.11.0", 48 | "html-loader": "^0.4.3", 49 | "html-webpack-plugin": "^2.22.0", 50 | "http-server": "^0.9.0", 51 | "husky": "^0.11.9", 52 | "istanbul": "^0.4.4", 53 | "istanbul-instrumenter-loader": "^1.1.0", 54 | "jasmine-core": "git+https://github.com/jasmine/jasmine.git#be6ff8b24cba355246df93d00d74a64de9e580ad", 55 | "jasmine-spec-reporter": "^2.7.0", 56 | "karma": "1.1.2", 57 | "karma-chrome-launcher": "1.0.1", 58 | "karma-coverage": "1.1.1", 59 | "karma-firefox-launcher": "1.0.0", 60 | "karma-jasmine": "^1.1.0", 61 | "karma-jasmine-diff-reporter": "^0.6.3", 62 | "karma-phantomjs-launcher": "1.0.1", 63 | "karma-spec-reporter": "0.0.26", 64 | "karma-webpack": "^1.8.0", 65 | "linklocal": "git+https://github.com/theoy/linklocal.git#3f939171c3c925f2af831d78a3f2fbf9caa3002e", 66 | "lodash": "^4.17.2", 67 | "ngtemplate-loader": "git+https://github.com/wearymonkey/ngtemplate-loader.git#63e3461d8b1298de913e3528766068260915ae1f", 68 | "node-sass": "^3.8.0", 69 | "npm-run-all": "^2.3.0", 70 | "open": "0.0.5", 71 | "phantomjs-prebuilt": "2.1.10", 72 | "protractor": "^4.0.9", 73 | "protractor-jasmine2-screenshot-reporter": "^0.3.2", 74 | "resolve-url-loader": "^1.6.0", 75 | "sass-loader": "^4.1.0", 76 | "semantic-release": "^4.3.5", 77 | "shx": "^0.1.4", 78 | "style-loader": "^0.13.1", 79 | "systemjs": "^0.19.36", 80 | "systemjs-plugin-babel": "0.0.15", 81 | "ts-node": "^1.3.0", 82 | "typedoc": "^0.5.0", 83 | "typescript": "^2.1.4", 84 | "url-loader": "^0.5.7", 85 | "validate-commit-msg": "^2.8.2", 86 | "webpack": "^2.1.0-beta.28", 87 | "webpack-dev-server": "^2.2.0-rc.0", 88 | "webpack-merge": "^1.1.1", 89 | "webpack-validator": "^2.3.0" 90 | }, 91 | "scripts": { 92 | "build:all": "run-s build:full build:demo-apps", 93 | "build:demo-apps": "shx ls -d demo-apps/*/ | bulk -c \"npm run build\"", 94 | "prebuild": "npm run clean", 95 | "build": "run-p tsc \"webpack -- --progress --profile --env.debug\"", 96 | "prebuild:prod": "npm run clean", 97 | "build:prod": "run-p tsc \"webpack -- --progress --profile --env.prod\"", 98 | "prebuild:full": "npm run clean", 99 | "build:full": "run-p tsc \"webpack -- --progress --profile --env.prod --env.debug\"", 100 | "clean:demo-apps": "shx ls -d demo-apps/*/ | bulk -c \"npm run clean\"", 101 | "clean:all": "run-p clean clean:demo-apps", 102 | "clean": "shx rm -rf bundles out demo-site/api-docs index.{js,js.map,d.ts} src/**/*.{js,js.map,d.ts} test/specs/**/*.{js,js.map,d.ts} test/util/**/*.{js,js.map,d.ts}", 103 | "cm": "git add -A && git-cz", 104 | "commitmsg": "validate-commit-msg", 105 | "doc-deploy": "gh-pages -d demo-site", 106 | "predoc": "shx rm -rf demo-site/api-docs", 107 | "doc": "typedoc --options typedoc.json index.ts", 108 | "e2e-server": "http-server demo-apps -c-1", 109 | "e2e-server:ci": "http-server demo-apps -s -c-1 &", 110 | "e2e": "npm run build:all && npm run e2e-only", 111 | "e2e:ci": "protractor e2e/protractor-travis.config", 112 | "e2e-only": "protractor e2e/protractor.config.js", 113 | "poste2e-only": "node ./scripts/open-e2e-report", 114 | "install:demo-apps": "shx ls -d demo-apps/*/ | bulk -c \"npm install\"", 115 | "link:demo-apps": "shx ls -d demo-apps/*/ | bulk -c \"npm run linklocal\"", 116 | "precommit": "npm run tsc", 117 | "semantic-release": "semantic-release pre && npm publish && semantic-release post", 118 | "serve:demo": "cd demo-apps/es5 && npm start", 119 | "serve:docs-site": "http-server demo-site -o -c-1", 120 | "_setup:common": "run-s build:full install:demo-apps link:demo-apps", 121 | "setup:ci": "npm run _setup:common", 122 | "setup": "run-p _setup:common update-webdriver", 123 | "test": "karma start", 124 | "test:w": "karma start --no-single-run --auto-watch", 125 | "test:debug": "karma start --no-single-run", 126 | "tsc": "tsc", 127 | "unlink:demo-apps": "shx ls -d demo-apps/*/ | bulk -c \"npm run unlinklocal\"", 128 | "update-webdriver": "webdriver-manager update", 129 | "validate-webpack": "webpack-validator webpack.config.js --env.dev --env.test --env.prod", 130 | "webpack": "webpack" 131 | }, 132 | "dependencies": { 133 | "@types/angular": "^1.5.13" 134 | }, 135 | "peerDependencies": { 136 | "angular": "^1.2" 137 | }, 138 | "config": { 139 | "commitizen": { 140 | "path": "./node_modules/cz-conventional-changelog" 141 | }, 142 | "validate-commit-msg": { 143 | "types": "conventional-commit-types", 144 | "helpMessage": "To help create valid commit messages consider using `npm run cm` instead of `git commit`" 145 | } 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /scripts/open-e2e-report.js: -------------------------------------------------------------------------------- 1 | var open = require("open"); 2 | open("./out/test/end2end/reports/e2e.html"); -------------------------------------------------------------------------------- /scripts/webpack/libParts.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | const ExtractTextPlugin = require("extract-text-webpack-plugin"); 4 | const merge = require('webpack-merge'); 5 | const webpack = require('webpack'); 6 | 7 | module.exports = createLibraryParts; 8 | 9 | function createLibraryParts(rootDir, env = {}) { 10 | const commonParts = require('./parts')(rootDir, env); 11 | const pkg = require(path.join(rootDir, 'package')); 12 | const libraryName = pkg.name; 13 | 14 | return Object.assign({}, commonParts, { 15 | asUmdLibrary, 16 | banner, 17 | extractSass, 18 | excludeAngular, 19 | inlineHtmlTemplates 20 | }); 21 | 22 | ///// 23 | 24 | 25 | function asUmdLibrary() { 26 | const filename = env.prod ? `[name].min.js` : `[name].js`; 27 | return { 28 | entry: { 29 | [libraryName]: path.join(rootDir, 'index.ts') 30 | }, 31 | // tells webpack not to include in bundle require'd node specific objects (eg path) 32 | target: 'node', 33 | output: { 34 | path: path.join(rootDir, 'bundles'), 35 | filename: filename, 36 | library: libraryName, 37 | libraryTarget: 'umd', 38 | umdNamedDefine: false 39 | } 40 | }; 41 | } 42 | 43 | function banner() { 44 | // warning: this conflicts with ExtractTextPlugin used to extract styles into seperate bundle 45 | const text = `/*! ngTable v${pkg.version} by Vitalii Savchuk(esvit666@gmail.com) - ` + 46 | 'https://github.com/esvit/ng-table - New BSD License */\n'; 47 | return { 48 | plugins: [ 49 | new webpack.BannerPlugin({ banner: text, entryOnly: true }) 50 | ] 51 | }; 52 | } 53 | 54 | function excludeAngular() { 55 | return { 56 | externals: { 57 | angular: 'angular' 58 | } 59 | } 60 | } 61 | 62 | /** 63 | * Extracts styles into a seperate bundle 64 | */ 65 | function extractSass(files) { 66 | 67 | // note: The way we're setting up webpack here seems a bit of a hack: 68 | // 69 | // Although the setup creates two bundles seperating the js and css as desired, 70 | // it's also producing an extra styles.js file which we're throwing away/ignoring. 71 | // The alternative, more supported way of things, is to leave the css inline 72 | // within js and let the styles plugin add the css at runtime to the html page. 73 | // At the moment keeping with the extracted css as: 74 | // 1. more familar to angular 1 developers (?) 75 | // 2. maintains backwards compatibility with the existing apps that expects 76 | // the css to be delivered to the browser as a seperate file 77 | 78 | const filename = env.prod ? `${libraryName}.min.css` : `${libraryName}.css`; 79 | const extractor = new ExtractTextPlugin(filename); 80 | let loader; 81 | if (env.debug || env.prod) { 82 | loader = 'css-loader?sourceMap!sass-loader?sourceMap'; 83 | } else { 84 | loader = 'css-loader!sass-loader'; 85 | } 86 | return { 87 | entry: { 88 | styles: files 89 | }, 90 | module: { 91 | rules: [ 92 | { 93 | test: /\.scss$/, 94 | loader: extractor.extract(loader), 95 | include: files 96 | } 97 | ] 98 | }, 99 | plugins: [ 100 | extractor 101 | ] 102 | }; 103 | } 104 | 105 | function inlineHtmlTemplates() { 106 | return { 107 | module: { 108 | rules: [ 109 | { 110 | test: /\.html$/, 111 | loaders: ['ngtemplate-loader?requireAngular&relativeTo=/src/browser/&prefix=ng-table/', 'html-loader'] 112 | } 113 | ] 114 | } 115 | }; 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /scripts/webpack/multiConfig.js: -------------------------------------------------------------------------------- 1 | module.exports = function (partsFactory) { 2 | return function multiconfig(sourceDir, env, configFactory) { 3 | let configs = []; 4 | if (env.prod) { 5 | let prodEnv = Object.assign({}, env, { debug: false }); 6 | configs.push(configFactory(prodEnv, partsFactory(sourceDir, prodEnv))); 7 | } 8 | if (env.debug) { 9 | let debugEnv = Object.assign({}, env, { prod: false }); 10 | configs.push(configFactory(debugEnv, partsFactory(sourceDir, debugEnv))); 11 | } 12 | if (!env.debug && !env.prod) { 13 | configs.push(configFactory(env, partsFactory(sourceDir, env))); 14 | } 15 | return configs; 16 | } 17 | }; 18 | 19 | -------------------------------------------------------------------------------- /scripts/webpack/parts.js: -------------------------------------------------------------------------------- 1 | const merge = require('webpack-merge'); 2 | const webpack = require('webpack'); 3 | const path = require('path'); 4 | 5 | module.exports = createParts; 6 | 7 | function createParts(rootDir, env) { 8 | 9 | return { 10 | es6, 11 | forEnvironment, 12 | prodOptimize, 13 | testCoverage, 14 | typescript 15 | }; 16 | 17 | //////// 18 | 19 | function es6() { 20 | return { 21 | module: { 22 | rules: [ 23 | { test: /\.js$/, loaders: ['babel-loader?cacheDirectory'], exclude: /node_modules/ } 24 | ] 25 | } 26 | } 27 | } 28 | 29 | function prodOptimize() { 30 | return { 31 | plugins: [ 32 | new webpack.LoaderOptionsPlugin({ 33 | minimize: true, 34 | debug: false, 35 | quiet: true, 36 | }), 37 | new webpack.DefinePlugin({ 38 | 'process.env': { 39 | NODE_ENV: '"production"', 40 | }, 41 | }), 42 | new webpack.optimize.UglifyJsPlugin({ 43 | compress: { 44 | screw_ie8: true, // eslint-disable-line 45 | warnings: false, 46 | }, 47 | comments: false, 48 | sourceMap: true 49 | }) 50 | ] 51 | }; 52 | } 53 | 54 | function forEnvironment() { 55 | if (env.prod) { 56 | return merge( 57 | { 58 | devtool: 'source-map', 59 | bail: true 60 | }, 61 | prodOptimize() 62 | ); 63 | } else if (env.debug) { 64 | return { 65 | output: { 66 | pathinfo: true 67 | }, 68 | // note: wanted to use eval-source-map to increase build times, but chrome would not stop on breakpoint 69 | // therefore instead using source-map 70 | devtool: 'source-map', 71 | performance: { 72 | hints: false 73 | } 74 | }; 75 | } else if (env.test) { 76 | return { 77 | devtool: 'inline-source-map' 78 | }; 79 | } else { 80 | return { 81 | devtool: 'eval' 82 | }; 83 | } 84 | } 85 | 86 | function testCoverage() { 87 | return { 88 | module: { 89 | rules: [ 90 | { 91 | enforce: 'post', 92 | test: /\.ts$/, 93 | exclude: [ 94 | /\.spec\.ts$/, 95 | /node_modules/ 96 | ], 97 | loader: 'istanbul-instrumenter-loader', 98 | query: { 99 | esModules: true 100 | } 101 | } 102 | ] 103 | } 104 | }; 105 | } 106 | 107 | function typescript(tsconfig = 'tsconfig.json') { 108 | const tsconfigPath = path.resolve(rootDir, tsconfig) 109 | return { 110 | // Currently we need to add '.ts' to the resolve.extensions array. 111 | resolve: { 112 | extensions: ['.ts', '.tsx', '.js', '.jsx'] 113 | }, 114 | module: { 115 | rules: [ 116 | { 117 | test: /\.ts$/, 118 | exclude: /node_modules/, 119 | loaders: [`awesome-typescript-loader?tsconfig=${tsconfigPath}`, 'angular1-template-loader'] 120 | } 121 | ] 122 | } 123 | }; 124 | } 125 | } -------------------------------------------------------------------------------- /src/browser/filterRow.html: -------------------------------------------------------------------------------- 1 | 2 | 4 |
6 |
7 | 8 | 9 | -------------------------------------------------------------------------------- /src/browser/filters/number.html: -------------------------------------------------------------------------------- 1 | 3 | -------------------------------------------------------------------------------- /src/browser/filters/select-multiple.html: -------------------------------------------------------------------------------- 1 | 7 | -------------------------------------------------------------------------------- /src/browser/filters/select.html: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /src/browser/filters/text.html: -------------------------------------------------------------------------------- 1 | 3 | -------------------------------------------------------------------------------- /src/browser/groupRow.html: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | {{$selGroupTitle}} 8 | 12 | 19 | 20 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /src/browser/header.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/browser/index.ts: -------------------------------------------------------------------------------- 1 | import * as angular from 'angular'; 2 | import { ngTable } from './ngTable.directive'; 3 | import { NgTableColumn } from './ngTableColumn'; 4 | import { ngTableColumnsBinding } from './ngTableColumnsBinding.directive'; 5 | import { NgTableController } from './ngTableController'; 6 | import { ngTableDynamic } from './ngTableDynamic.directive'; 7 | import { NgTableFilterConfigProvider, NgTableFilterConfig } from './ngTableFilterConfig'; 8 | import { ngTableFilterRow } from './ngTableFilterRow.directive'; 9 | import { NgTableFilterRowController } from './ngTableFilterRowController'; 10 | import { ngTableGroupRow } from './ngTableGroupRow.directive'; 11 | import { NgTableGroupRowController } from './ngTableGroupRowController'; 12 | import { ngTablePagination } from './ngTablePagination.directive'; 13 | import { ngTableSelectFilterDs } from './ngTableSelectFilterDs.directive'; 14 | import { ngTableSorterRow } from './ngTableSorterRow.directive'; 15 | import { NgTableSorterRowController } from './ngTableSorterRowController'; 16 | import './filters/number.html'; 17 | import './filters/select.html'; 18 | import './filters/select-multiple.html'; 19 | import './filters/text.html'; 20 | import './pager.html'; 21 | import './header.html'; 22 | 23 | const ngTableBrowserModule = angular.module('ngTable-browser', []) 24 | .directive('ngTable', ngTable) 25 | .service('ngTableColumn', NgTableColumn) 26 | .directive('ngTableColumnsBinding', ngTableColumnsBinding) 27 | .controller('ngTableController', NgTableController) 28 | .directive('ngTableDynamic', ngTableDynamic) 29 | .provider('ngTableFilterConfig', NgTableFilterConfigProvider) 30 | .directive('ngTableFilterRow', ngTableFilterRow) 31 | .controller('ngTableFilterRowController', NgTableFilterRowController) 32 | .directive('ngTableGroupRow', ngTableGroupRow) 33 | .controller('ngTableGroupRowController', NgTableGroupRowController) 34 | .directive('ngTablePagination', ngTablePagination) 35 | .directive('ngTableSelectFilterDs', ngTableSelectFilterDs) 36 | .directive('ngTableSorterRow', ngTableSorterRow) 37 | .controller('ngTableSorterRowController', NgTableSorterRowController); 38 | 39 | export * from './public-interfaces'; 40 | export { NgTableController, ngTableBrowserModule }; 41 | export * from './ngTableFilterConfig'; -------------------------------------------------------------------------------- /src/browser/ngTableColumn.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ngTable: Table + Angular JS 3 | * 4 | * @author Vitalii Savchuk 5 | * @url https://github.com/esvit/ng-table/ 6 | * @license New BSD License 7 | */ 8 | 9 | import { IScope } from 'angular'; 10 | import * as ng1 from 'angular'; 11 | import { ColumnDef, ColumnDefPartial, DynamicTableColDef } from './public-interfaces'; 12 | 13 | /** 14 | * @private 15 | */ 16 | function isScopeLike(object: any) { 17 | return object != null && ng1.isFunction(object.$new); 18 | } 19 | 20 | /** 21 | * @private 22 | * Service to construct a $column definition used by {@link ngTable ngTable} directive 23 | */ 24 | export class NgTableColumn { 25 | static $inject: string[] = []; 26 | 27 | /** 28 | * Creates a $column for use within a header template 29 | * 30 | * @param column the initial definition for $column to build 31 | * @param defaultScope the $scope to supply to the $column getter methods when not supplied by caller 32 | * @param columns a reference to the $columns array to make available on the context supplied to the 33 | * $column getter methods 34 | */ 35 | buildColumn(column: TCol, defaultScope: IScope, columns: ColumnDef[]): ColumnDef { 36 | // note: we're not modifying the original column object. This helps to avoid unintended side affects 37 | const extendedCol = Object.create(column); 38 | const defaults = this.createDefaults(); 39 | for (const prop in defaults) { 40 | if (extendedCol[prop] === undefined) { 41 | extendedCol[prop] = defaults[prop]; 42 | } 43 | if (!ng1.isFunction(extendedCol[prop])) { 44 | // wrap raw field values with "getter" functions 45 | // - this is to ensure consistency with how ngTable.compile builds columns 46 | // - note that the original column object is being "proxied"; this is important 47 | // as it ensure that any changes to the original object will be returned by the "getter" 48 | const getterSetter = function getterSetter(/*[value] || [$scope, locals]*/) { 49 | if (arguments.length === 1 && !isScopeLike(arguments[0])) { 50 | (getterSetter as any).assign(null, arguments[0]); 51 | } else { 52 | return column[prop]; 53 | } 54 | }; 55 | (getterSetter as any).assign = function ($scope: IScope, value: any) { 56 | column[prop] = value; 57 | }; 58 | extendedCol[prop] = getterSetter; 59 | } 60 | // satisfy the arguments expected by the function returned by parsedAttribute in the ngTable directive 61 | const getterFn = extendedCol[prop]; 62 | extendedCol[prop] = function () { 63 | if (arguments.length === 1 && !isScopeLike(arguments[0])) { 64 | getterFn.assign(defaultScope, arguments[0]); 65 | } else { 66 | const scope = arguments[0] || defaultScope; 67 | const context = Object.create(scope); 68 | ng1.extend(context, { 69 | $column: extendedCol, 70 | $columns: columns 71 | }); 72 | return getterFn.call(column, context); 73 | } 74 | }; 75 | if (getterFn.assign) { 76 | extendedCol[prop].assign = getterFn.assign; 77 | } else { 78 | const wrappedGetterFn = extendedCol[prop]; 79 | let localValue: any; 80 | const getterSetter = function getterSetter(/*[value] || [$scope, locals]*/) { 81 | if (arguments.length === 1 && !isScopeLike(arguments[0])) { 82 | (getterSetter as any).assign(null, arguments[0]); 83 | } else { 84 | return localValue != undefined ? localValue : wrappedGetterFn.apply(extendedCol, arguments); 85 | } 86 | }; 87 | (getterSetter as any).assign = function ($scope: IScope, value: any) { 88 | localValue = value; 89 | }; 90 | extendedCol[prop] = getterSetter; 91 | } 92 | } 93 | return extendedCol as ColumnDef; 94 | } 95 | 96 | private createDefaults() { 97 | return { 98 | 'class': this.createGetterSetter(''), 99 | filter: this.createGetterSetter(false), 100 | groupable: this.createGetterSetter(false), 101 | filterData: ng1.noop, 102 | headerTemplateURL: this.createGetterSetter(false), 103 | headerTitle: this.createGetterSetter(''), 104 | sortable: this.createGetterSetter(false), 105 | show: this.createGetterSetter(true), 106 | title: this.createGetterSetter(''), 107 | titleAlt: this.createGetterSetter('') 108 | }; 109 | } 110 | 111 | private createGetterSetter(initialValue: any) { 112 | let value = initialValue; 113 | const getterSetter = function getterSetter(/*[value] || [$scope, locals]*/) { 114 | if (arguments.length === 1 && !isScopeLike(arguments[0])) { 115 | (getterSetter as any).assign(null, arguments[0]); 116 | } else { 117 | return value; 118 | } 119 | }; 120 | (getterSetter as any).assign = function ($scope: IScope, newValue: any) { 121 | value = newValue; 122 | }; 123 | return getterSetter; 124 | } 125 | } -------------------------------------------------------------------------------- /src/browser/ngTableColumnsBinding.directive.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ngTable: Table + Angular JS 3 | * 4 | * @author Vitalii Savchuk 5 | * @url https://github.com/esvit/ng-table/ 6 | * @license New BSD License 7 | */ 8 | 9 | import { IAugmentedJQuery, IAttributes, IDirective, IParseService } from 'angular'; 10 | import { TableScope } from './ngTableController'; 11 | import { ColumnDef } from './public-interfaces'; 12 | 13 | /** 14 | * @private 15 | */ 16 | interface InputAttributes extends IAttributes { 17 | ngTableColumnsBinding: string; 18 | } 19 | 20 | ngTableColumnsBinding.$inject = ["$parse"]; 21 | 22 | /** 23 | * One-way data binds the $columns array generated by ngTable/ngTableDynamic to the specified 24 | * expression. 25 | * This allows the $columns array created for the table to be accessed outside of the html table 26 | * markup. 27 | * 28 | * @ngdoc directive 29 | * 30 | * @example 31 | * ```html 32 | * 33 | * ``` 34 | */ 35 | export function ngTableColumnsBinding($parse: IParseService) : IDirective { 36 | const directive = { 37 | restrict: 'A', 38 | link: linkFn 39 | }; 40 | return directive; 41 | 42 | function linkFn($scope: TableScope, $element: IAugmentedJQuery, $attrs: InputAttributes){ 43 | const setter = $parse($attrs.ngTableColumnsBinding).assign; 44 | if (setter){ 45 | $scope.$watch('$columns', newColumns => { 46 | const shallowClone = (newColumns || []).slice(0); 47 | setter($scope, shallowClone); 48 | }); 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /src/browser/ngTableDynamic.directive.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ngTable: Table + Angular JS 3 | * 4 | * @author Vitalii Savchuk 5 | * @url https://github.com/esvit/ng-table/ 6 | * @license New BSD License 7 | */ 8 | 9 | import { IAugmentedJQuery, IDirective, IScope } from 'angular'; 10 | import * as ng1 from 'angular'; 11 | import { ColumnDef, DynamicTableColDef, DynamicTableHtmlAttributes } from './public-interfaces'; 12 | import { NgTableController } from './ngTableController'; 13 | 14 | interface ScopeExtensions { 15 | $columns: ColumnDef[] 16 | } 17 | 18 | function toArray(arr: ArrayLike) { 19 | return Array.prototype.slice.call(arr) as T[]; 20 | } 21 | 22 | ngTableDynamic.$inject = []; 23 | 24 | /** 25 | * A dynamic version of the {@link ngTable ngTable} directive that accepts a dynamic list of columns 26 | * definitions to render 27 | * @ngdoc directive 28 | * 29 | * @example 30 | * ```html 31 | *
32 | * 33 | * 34 | * 35 | *
{{row[col.field]}}
36 | * ``` 37 | */ 38 | export function ngTableDynamic(): IDirective { 39 | 40 | return { 41 | restrict: 'A', 42 | priority: 1001, 43 | scope: true, 44 | controller: 'ngTableController', 45 | compile: function (tElement: IAugmentedJQuery) { 46 | 47 | const tRows = toArray(tElement[0].getElementsByTagName('tr')); 48 | const tRow = tRows.filter(tr => !ng1.element(tr).hasClass('ng-table-group'))[0]; 49 | 50 | if (!tRow) { 51 | return undefined; 52 | } 53 | 54 | toArray(tRow.getElementsByTagName('td')).forEach(tCell => { 55 | const el = ng1.element(tCell); 56 | const getAttrValue = (attr: string) => { 57 | return el.attr('x-data-' + attr) || el.attr('data-' + attr) || el.attr(attr); 58 | }; 59 | 60 | // this used in responsive table 61 | const titleExpr = getAttrValue('title'); 62 | if (!titleExpr) { 63 | el.attr('data-title-text', '{{$columns[$index].titleAlt(this) || $columns[$index].title(this)}}'); 64 | } 65 | const showExpr = el.attr('ng-if'); 66 | if (!showExpr) { 67 | el.attr('ng-if', '$columns[$index].show(this)'); 68 | } 69 | }); 70 | return function (scope: IScope & ScopeExtensions, element: IAugmentedJQuery, attrs: DynamicTableHtmlAttributes, controller: NgTableController) { 71 | const expr = controller.parseNgTableDynamicExpr(attrs.ngTableDynamic); 72 | 73 | controller.setupBindingsToInternalScope(expr.tableParams); 74 | controller.compileDirectiveTemplates(); 75 | 76 | scope.$watchCollection(expr.columns, (newCols/*, oldCols*/) => { 77 | scope.$columns = controller.buildColumns(newCols); 78 | controller.loadFilterData(scope.$columns); 79 | }); 80 | }; 81 | } 82 | }; 83 | } -------------------------------------------------------------------------------- /src/browser/ngTableFilterConfig.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ngTable: Table + Angular JS 3 | * 4 | * @author Vitalii Savchuk 5 | * @url https://github.com/esvit/ng-table/ 6 | * @license New BSD License 7 | */ 8 | 9 | import * as ng1 from 'angular'; 10 | import { IServiceProvider, auto } from 'angular'; 11 | import { assignPartialDeep } from '../shared'; 12 | import { FilterTemplateDef } from './public-interfaces'; 13 | 14 | /** 15 | * Configuration values that determine the behaviour of the `ngTableFilterConfig` service 16 | */ 17 | export class FilterConfigValues { 18 | /** 19 | * The default base url to use when deriving the url for a filter template given just an alias name 20 | */ 21 | defaultBaseUrl = 'ng-table/filters/'; 22 | /** 23 | * The extension to use when deriving the url of a filter template when given just an alias name 24 | */ 25 | defaultExt = '.html'; 26 | /** 27 | * A map of alias names and their corrosponding urls. A lookup against this map will be used 28 | * to find the url matching an alias name. 29 | * If no match is found then a url will be derived using the following pattern `${defaultBaseUrl}${aliasName}.${defaultExt}` 30 | */ 31 | aliasUrls: { [name: string]: string } = {}; 32 | } 33 | 34 | export type FilterConfigValuesPartial = Partial 35 | 36 | /** 37 | * The angular provider used to configure the behaviour of the `NgTableFilterConfig` service. 38 | */ 39 | export class NgTableFilterConfigProvider implements IServiceProvider { 40 | static $inject = ['$injector']; 41 | $get: () => NgTableFilterConfig; 42 | private config: FilterConfigValues; 43 | constructor($injector: auto.IInjectorService) { 44 | this.$get = () => { 45 | return $injector.instantiate(NgTableFilterConfig, { config: ng1.copy(this.config) }); 46 | } 47 | this.$get.$inject = []; 48 | this.resetConfigs(); 49 | } 50 | 51 | /** 52 | * Reset back to factory defaults the config values that `NgTableFilterConfig` service will use 53 | */ 54 | resetConfigs() { 55 | this.config = new FilterConfigValues(); 56 | } 57 | 58 | /** 59 | * Set the config values used by `NgTableFilterConfig` service 60 | */ 61 | setConfig(customConfig: FilterConfigValuesPartial) { 62 | this.config = assignPartialDeep(ng1.copy(this.config), customConfig); 63 | } 64 | } 65 | 66 | /** 67 | * Exposes configuration values and methods used to return the location of the html 68 | * templates used to render the filter row of an ng-table directive 69 | */ 70 | export class NgTableFilterConfig { 71 | static $inject = ['config']; 72 | constructor( 73 | /** 74 | * Readonly copy of the final values used to configure the service. 75 | */ 76 | public readonly config: FilterConfigValues 77 | ) { } 78 | 79 | /** 80 | * Return the url of the html filter template registered with the alias supplied 81 | */ 82 | getUrlForAlias(aliasName: string, filterKey?: string) { 83 | return this.config.aliasUrls[aliasName] || this.config.defaultBaseUrl + aliasName + this.config.defaultExt; 84 | } 85 | 86 | /** 87 | * Return the url of the html filter template for the supplied definition and key. 88 | * For more information see the documentation for {@link FilterTemplateMap} 89 | */ 90 | getTemplateUrl(filterDef: string | FilterTemplateDef, filterKey?: string) { 91 | let filterName: string; 92 | if (typeof filterDef !== 'string') { 93 | filterName = filterDef.id; 94 | } else { 95 | filterName = filterDef; 96 | } 97 | if (filterName.indexOf('/') !== -1) { 98 | return filterName; 99 | } 100 | 101 | return this.getUrlForAlias(filterName, filterKey); 102 | } 103 | } -------------------------------------------------------------------------------- /src/browser/ngTableFilterRow.directive.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ngTable: Table + Angular JS 3 | * 4 | * @author Vitalii Savchuk 5 | * @url https://github.com/esvit/ng-table/ 6 | * @license New BSD License 7 | */ 8 | 9 | const templateUrl = require('./filterRow.html'); 10 | 11 | ngTableFilterRow.$inject = []; 12 | 13 | /** 14 | * directive that renders the filter header row for a table 15 | * @ngdoc directive 16 | * @example 17 | * ```html 18 | * 19 | * ``` 20 | */ 21 | export function ngTableFilterRow(){ 22 | const directive = { 23 | restrict: 'E', 24 | replace: true, 25 | templateUrl: templateUrl, 26 | scope: true, 27 | controller: 'ngTableFilterRowController', 28 | controllerAs: '$ctrl' 29 | }; 30 | return directive; 31 | } -------------------------------------------------------------------------------- /src/browser/ngTableFilterRowController.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ngTable: Table + Angular JS 3 | * 4 | * @author Vitalii Savchuk 5 | * @url https://github.com/esvit/ng-table/ 6 | * @license New BSD License 7 | */ 8 | 9 | import { IScope } from 'angular'; 10 | import { FilterTemplateDef, FilterTemplateDefMap } from './public-interfaces'; 11 | import { NgTableFilterConfig } from './ngTableFilterConfig'; 12 | 13 | /** 14 | * @private 15 | */ 16 | export interface ScopeExtensions { 17 | getFilterPlaceholderValue(filterDef: string | FilterTemplateDef, filterKey?: string): string; 18 | } 19 | 20 | /** 21 | * Controller for the {@link ngTableFilterRow ngTableFilterRow} directive 22 | */ 23 | export class NgTableFilterRowController { 24 | static $inject = ['$scope', 'ngTableFilterConfig']; 25 | config: NgTableFilterConfig; 26 | constructor($scope: IScope & ScopeExtensions, ngTableFilterConfig: NgTableFilterConfig) { 27 | this.config = ngTableFilterConfig; 28 | 29 | // todo: stop doing this. Why? 30 | // * scope inheritance makes it hard to know how supplies functions 31 | // * scope is not a concept in angular 2 32 | // make function available to filter templates 33 | $scope.getFilterPlaceholderValue = this.getFilterPlaceholderValue.bind(this); 34 | } 35 | 36 | getFilterCellCss(filter: FilterTemplateDefMap, layout: string) { 37 | if (layout !== 'horizontal') { 38 | return 's12'; 39 | } 40 | 41 | const size = Object.keys(filter).length; 42 | const width = parseInt((12 / size).toString(), 10); 43 | return 's' + width; 44 | } 45 | 46 | getFilterPlaceholderValue(filterDef: string | FilterTemplateDef, filterKey?: string) { 47 | if (typeof filterDef === 'string') { 48 | return ''; 49 | } else { 50 | return filterDef.placeholder; 51 | } 52 | } 53 | } -------------------------------------------------------------------------------- /src/browser/ngTableGroupRow.directive.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ngTable: Table + Angular JS 3 | * 4 | * @author Vitalii Savchuk 5 | * @url https://github.com/esvit/ng-table/ 6 | * @license New BSD License 7 | */ 8 | 9 | const templateUrl = require('./groupRow.html'); 10 | 11 | ngTableGroupRow.$inject = []; 12 | 13 | /** 14 | * directive that renders the group header row for a table 15 | * @ngdoc directive 16 | * @example 17 | * ```html 18 | * 19 | * ``` 20 | */ 21 | export function ngTableGroupRow(){ 22 | const directive = { 23 | restrict: 'E', 24 | replace: true, 25 | templateUrl: templateUrl, 26 | scope: true, 27 | controller: 'ngTableGroupRowController', 28 | controllerAs: '$ctrl' 29 | }; 30 | return directive; 31 | } -------------------------------------------------------------------------------- /src/browser/ngTableGroupRowController.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ngTable: Table + Angular JS 3 | * 4 | * @author Vitalii Savchuk 5 | * @url https://github.com/esvit/ng-table/ 6 | * @license New BSD License 7 | */ 8 | 9 | import { IPromise } from 'angular'; 10 | import { DataResult, GroupingFunc, Grouping, GroupSort } from '../core'; 11 | import { ColumnDef } from './public-interfaces'; 12 | import { TableScope } from './ngTableController'; 13 | 14 | /** 15 | * @private 16 | */ 17 | export interface ScopeExtensions { 18 | $selGroup: GroupingFunc | string; 19 | $selGroupTitle: string; 20 | } 21 | 22 | 23 | /** 24 | * Controller for the {@link ngTableGroupRow ngTableGroupRow} directive 25 | */ 26 | export class NgTableGroupRowController { 27 | static $inject = ['$scope']; 28 | private groupFns: Array | ColumnDef> = []; 29 | constructor(private $scope: TableScope & ScopeExtensions) { 30 | $scope.$watch>('params.group()', (newGrouping) => { 31 | this.setGroup(newGrouping); 32 | }, true); 33 | } 34 | 35 | getGroupables() { 36 | const groupableCols = this.$scope.$columns.filter($column => !!$column.groupable(this.$scope)); 37 | return this.groupFns.concat(groupableCols); 38 | } 39 | 40 | getGroupTitle(group: GroupingFunc | ColumnDef) { 41 | return this.isGroupingFunc(group) ? group.title : group.title(this.$scope); 42 | } 43 | 44 | 45 | getVisibleColumns() { 46 | return this.$scope.$columns.filter($column => $column.show(this.$scope)) 47 | } 48 | 49 | groupBy(group: GroupingFunc | ColumnDef) { 50 | if (this.isSelectedGroup(group)) { 51 | this.changeSortDirection(); 52 | } else { 53 | if (this.isGroupingFunc(group)) { 54 | this.$scope.params.group(group); 55 | } else { 56 | // it's OK, we know that groupable will return a string 57 | // this is guaranteed by getGroupables returning only 58 | // columns that return (truthy) strings 59 | this.$scope.params.group(group.groupable(this.$scope) as string); 60 | } 61 | } 62 | } 63 | 64 | isSelectedGroup(group: GroupingFunc | ColumnDef) { 65 | if (this.isGroupingFunc(group)) { 66 | return group === this.$scope.$selGroup; 67 | } else { 68 | return group.groupable(this.$scope) === this.$scope.$selGroup; 69 | } 70 | } 71 | 72 | toggleDetail() { 73 | this.$scope.params.settings().groupOptions.isExpanded = !this.$scope.params.settings().groupOptions.isExpanded; 74 | return this.$scope.params.reload(); 75 | } 76 | 77 | private changeSortDirection() { 78 | let newDirection: GroupSort; 79 | if (this.$scope.params.hasGroup(this.$scope.$selGroup, 'asc')) { 80 | newDirection = 'desc'; 81 | } else if (this.$scope.params.hasGroup(this.$scope.$selGroup, 'desc')) { 82 | newDirection = ''; 83 | } else { 84 | newDirection = 'asc'; 85 | } 86 | this.$scope.params.group(this.$scope.$selGroup, newDirection); 87 | } 88 | 89 | private findGroupColumn(groupKey: GroupingFunc | string) { 90 | return this.$scope.$columns.filter($column => $column.groupable(this.$scope) === groupKey)[0]; 91 | } 92 | 93 | private isGroupingFunc(val: ColumnDef | Grouping): val is GroupingFunc { 94 | return typeof val === 'function'; 95 | } 96 | 97 | private setGroup(grouping: Grouping) { 98 | const existingGroupCol = this.findGroupColumn(this.$scope.$selGroup); 99 | if (existingGroupCol && existingGroupCol.show.assign) { 100 | existingGroupCol.show.assign(this.$scope, true); 101 | } 102 | if (this.isGroupingFunc(grouping)) { 103 | this.groupFns = [grouping]; 104 | this.$scope.$selGroup = grouping; 105 | this.$scope.$selGroupTitle = grouping.title || ''; 106 | } else { 107 | // note: currently only one group is implemented 108 | const groupKey = Object.keys(grouping || {})[0]; 109 | const groupedColumn = this.findGroupColumn(groupKey); 110 | if (groupedColumn) { 111 | this.$scope.$selGroupTitle = groupedColumn.title(this.$scope); 112 | this.$scope.$selGroup = groupKey; 113 | if (groupedColumn.show.assign) { 114 | groupedColumn.show.assign(this.$scope, false); 115 | } 116 | } 117 | } 118 | } 119 | } -------------------------------------------------------------------------------- /src/browser/ngTablePagination.directive.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ngTable: Table + Angular JS 3 | * 4 | * @author Vitalii Savchuk 5 | * @url https://github.com/esvit/ng-table/ 6 | * @license New BSD License 7 | */ 8 | 9 | import * as ng1 from 'angular'; 10 | import { NgTableEventsChannel, PageButton } from '../core' 11 | import { TableScope } from './ngTableController'; 12 | 13 | interface ScopeExtensions { 14 | pages: PageButton[] 15 | } 16 | 17 | ngTablePagination.$inject = ['$compile', '$document', 'ngTableEventsChannel']; 18 | 19 | /** 20 | * Directive that renders the table pagination controls 21 | * @ngdoc directive 22 | */ 23 | export function ngTablePagination($compile: ng1.ICompileService, $document: ng1.IDocumentService, ngTableEventsChannel: NgTableEventsChannel): ng1.IDirective { 24 | 25 | return { 26 | restrict: 'A', 27 | scope: { 28 | 'params': '=ngTablePagination', 29 | 'templateUrl': '=' 30 | }, 31 | replace: false, 32 | link: function(scope: TableScope & ScopeExtensions, element: ng1.IAugmentedJQuery/*, attrs*/) { 33 | 34 | ngTableEventsChannel.onAfterReloadData(function(pubParams) { 35 | scope.pages = pubParams.generatePagesArray(); 36 | }, scope, function(pubParams){ 37 | return pubParams === scope.params; 38 | }); 39 | 40 | scope.$watch('templateUrl', function(templateUrl) { 41 | if (templateUrl === undefined) { 42 | return; 43 | } 44 | const template = ng1.element('
', $document); 45 | element.append(template); 46 | $compile(template)(scope); 47 | }); 48 | } 49 | }; 50 | } -------------------------------------------------------------------------------- /src/browser/ngTableSelectFilterDs.directive.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ngTable: Table + Angular JS 3 | * 4 | * @author Vitalii Savchuk 5 | * @url https://github.com/esvit/ng-table/ 6 | * @license New BSD License 7 | */ 8 | 9 | import { IAttributes, IDirective, IParseService, IQService, IPromise, IScope } from 'angular'; 10 | import { ColumnDef, SelectData, SelectDataFunc, SelectOption } from './public-interfaces'; 11 | 12 | /** 13 | * @private 14 | */ 15 | export interface InputAttributes extends IAttributes { 16 | ngTableSelectFilterDs: string; 17 | } 18 | 19 | /** 20 | * @private 21 | */ 22 | export interface ScopeExtensions { 23 | $selectData: SelectOption[] 24 | } 25 | 26 | ngTableSelectFilterDs.$inject = []; 27 | 28 | /** 29 | * Takes the array returned by $column.filterData and makes it available as `$selectData` on the `$scope`. 30 | * 31 | * The resulting `$selectData` array will contain an extra item that is suitable to represent the user 32 | * "deselecting" an item from a `