如何创build一个表格,用户可以在AngularJS中更改影响结果的值

我刚开始学习angularJS。 我的老板给了我一个Excel电子表格,他们希望我把这个表格放到网站上。

在Excel中,可以更改电子表格中的单元格,从而影响使用公式的其他单元格。

在我的申请到目前为止,我有一张桌子。 例如:

var app1 = angular.module('app1', []); app1.controller('ctrl1', function($scope) { }); 
 <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script> <!-- AngularJs controller --> <div ng-controller="ctrl1"> <!-- TABLE --> <main class="container-fluid wrapper"> <section class="row bg-white"> <div class="container"> <div class="col-xs-12"> <table id="example" class="table table-striped table-bordered" cellspacing="0" width="100%"> <!-- Table header --> <thead> <tr> <th>Type</th> <th>Length</th> <th>Width</th> <th>Area</th> <th>Qty</th> <th>Kilos</th> </tr> </thead> <!-- Table body --> <tbody> <tr> <td>Flax Door Half Hour</td> <td>2040</td> <td>926</td> <td>1.89</td> <td>1</td> <td>41.56</td> </tr> </tbody> </table> </div> </div> </section> </main> </div> 

我如何使每个单元格可编辑? 我如何做excel如公式,如= SUM(E8 * F8)* 22

这是演示: http : //www.syntaxsuccess.com/angular-2-samples/#/demo/spreadsheet

你可以从这里下载: https : //github.com/thelgevold/angular-2-samples

组件代码:

 import {Component, Input, AfterViewChecked} from '@angular/core'; import {NgModel} from '@angular/common'; import {SpreadsheetModel} from './spreadsheetModel'; import {KeyMap} from './key-map'; import {HeaderRowService} from './header-row-service'; @Component({ selector: 'spreadsheet', templateUrl: './components/spreadsheet/spreadsheet.html' }) export class Spreadsheet implements AfterViewChecked { model:SpreadsheetModel; @Input() rows:Number; @Input() columns:Number; constructor(){ this.model = new SpreadsheetModel(10,4); this.header = HeaderRowService.createHeader(this.model.rows[0].columns.length); this.visibleRows = this.getVisibleRows(); } getHeader(){ return HeaderRowService.createHeader(this.model.rows[0].columns.length); } navigate($event){ this.model.navigate($event.keyCode); this.visibleRows = this.getVisibleRows(); } ngAfterViewChecked(){ let cell = document.getElementById(this.model.current.rowIndex + '-' + this.model.current.columnIndex); cell.focus(); } getVisibleRows(){ return this.model.rows.filter((row) => row.rowIndex >= this.model.start && row.rowIndex < this.model.end); } getActive(col){ if(col === this.model.current){ return 'active-cell'; } } } 

型号代码

 import {KeyMap} from './key-map'; import {Row} from './row'; import {Column} from './column'; export class SpreadsheetModel{ rows:Array<Row>; current:Column; start:number; end:number; constructor(public rowCount, public columnCount){ this.rows = []; this.start = 0; this.end = rowCount; for(let i = 0; i < this.rowCount; i++){ this.rows.push(new Row(i,this.columnCount)); } this.current = this.rows[0].columns[0]; } selectColumn(col){ this.current = col; } navigate(keyCode){ const navDirection = KeyMap.getNavigationDirection(keyCode); if(navDirection.down){ this.ensureRow(); this.current = this.rows[this.current.rowIndex + 1].columns[this.current.columnIndex]; this.adjustRowRangeDownward(); } if(navDirection.up){ if(this.current.rowIndex === 0){ return; } this.current = this.rows[this.current.rowIndex - 1].columns[this.current.columnIndex]; this.adjustRowRangeUpward(); } if(navDirection.left){ if(this.current.columnIndex === 0){ return; } this.current = this.rows[this.current.rowIndex].columns[this.current.columnIndex - 1]; } if(navDirection.right){ if(this.current.columnIndex === this.columnCount - 1){ return; } this.current = this.rows[this.current.rowIndex].columns[this.current.columnIndex + 1]; } } adjustRowRangeUpward(){ if(this.current.rowIndex < this.start){ this.shiftRowsBy(-1); } } adjustRowRangeDownward(){ if(this.current.rowIndex === this.end){ this.shiftRowsBy(1); } } shiftRowsBy(offset){ this.start = this.start + offset; this.end = this.end + offset; } ensureRow(){ if(this.current.rowIndex + 1 >= this.rows.length){ this.rows.push(new Row(this.current.rowIndex + 1,this.columnCount)); } } } 

实体

 import {Column} from './column'; //Row export class Row{ columns:Array; constructor(public rowIndex, public columnCount){ this.columns = []; for(let j = 0; j < this.columnCount; j++){ this.columns.push(new Column(j,this.rowIndex)); } } } //Column export class Column{ cellValue:String; constructor(public columnIndex,public rowIndex){ this.cellValue = ''; } } 

查看(模板代码HTML):

 <table id="spreadsheet"> <tr> <td class="row-number-column"></td> <td class="columnHeader" *ngFor="let columnHeader of header">{{columnHeader}}</td> </tr> <tr *ngFor="let row of visibleRows"> <td class="row-number-column">{{row.rowIndex}}</td> <td *ngFor="let col of row.columns"> <input data-id="{{col.rowIndex}}-{{col.columnIndex}}" [value]="col.cellValue" (input)="col.cellValue = $event.target.value" (click)="model.selectColumn(col)" (keyup)="navigate($event)" /> </td> </tr> </table> 

希望它可以帮助你。 我从这个http://www.syntaxsuccess.com/viewarticle/virtualized-spreadsheet-component-in-angular-2.0复&#x5236;

这是很长的事情,特别是公式的事情,但以下可以给你一个出发点:

TD中的每个可编辑值都应该是一个指令 。

 <td><super-edit value="2040"></super-edit></td> 

这样该指令可以处理我称为editMode的元素的状态

当你点击一个TD元素时,editMode被设置为true,并使用ng-if使input变为可见。

TD元素的值和input字段使用ng-model链接。这样修改input内的值将更新TD的值。

要离开editMode我select隐藏input,当你用ng-blur点击它之外

  <tbody> <tr> <td>Flax Door Half Hour</td> <td><super-edit value="2040"></super-edit></td> <td><super-edit value="926"></super-edit></td> <td><super-edit value="1.89"></super-edit></td> <td><super-edit value="1"></super-edit></td> <td><super-edit value="41.56"></super-edit></td> </tr> </tbody> function superEdit() { return { scope: {}, restrict: 'E', bindToController: { value: '=' }, template: [ '<span ng-if="!c.editMode" ng-click="c.editMode = true">{{c.value}}</span>', '<input type="text" ng-model="c.value" ng-if="c.editMode" ng-blur="c.editMode = false">' ].join(''), controller: SuperController, controllerAs: 'c' } } function SuperController() { this.editMode = false; } angular.module('myApp', []); angular .module('myApp') .directive('superEdit', superEdit); 

小提琴