mirror of
https://github.com/gristlabs/grist-core.git
synced 2024-10-27 20:44:07 +00:00
(core) Reference columns weren't added to Raw Data Views
Summary: - Adding a column through 'Add Reference Column' adds it to Raw Data - Migrating RefSelect.js to typescript - Extending one of the tests Test Plan: updated Reviewers: cyprien Reviewed By: cyprien Subscribers: cyprien Differential Revision: https://phab.getgrist.com/D3513
This commit is contained in:
parent
f91f45b26d
commit
ddb80f111e
@ -1,232 +0,0 @@
|
||||
var _ = require('underscore');
|
||||
var ko = require('knockout');
|
||||
var Promise = require('bluebird');
|
||||
var koArray = require('../lib/koArray');
|
||||
var dispose = require('../lib/dispose');
|
||||
var tableUtil = require('../lib/tableUtil');
|
||||
var gutil = require('app/common/gutil');
|
||||
const {colors, testId} = require('app/client/ui2018/cssVars');
|
||||
const {cssFieldEntry, cssFieldLabel} = require('app/client/ui/VisibleFieldsConfig');
|
||||
const {dom, fromKo, styled} = require('grainjs');
|
||||
const {icon} = require('app/client/ui2018/icons');
|
||||
const {menu, menuItem, menuText} = require('app/client/ui2018/menus');
|
||||
|
||||
/**
|
||||
* Builder for the reference display multiselect.
|
||||
*/
|
||||
function RefSelect(options) {
|
||||
this.docModel = options.docModel;
|
||||
this.origColumn = options.origColumn;
|
||||
this.colId = this.origColumn.colId;
|
||||
|
||||
// Indicates whether this is a ref col that references a different table.
|
||||
// (That's the only time when RefSelect is offered.)
|
||||
this.isForeignRefCol = this.autoDispose(ko.computed(() => {
|
||||
const t = this.origColumn.refTable();
|
||||
return Boolean(t && t.getRowId() !== this.origColumn.parentId());
|
||||
}));
|
||||
|
||||
// Computed for the current fieldBuilder's field, if it exists.
|
||||
this.fieldObs = this.autoDispose(ko.computed(() => {
|
||||
let builder = options.fieldBuilder();
|
||||
return builder ? builder.field : null;
|
||||
}));
|
||||
|
||||
// List of valid cols in the currently referenced table.
|
||||
this._validCols = this.autoDispose(ko.computed(() => {
|
||||
var refTable = this.origColumn.refTable();
|
||||
if (refTable) {
|
||||
return refTable.columns().all().filter(col => !col.isHiddenCol() &&
|
||||
!gutil.startsWith(col.type(), 'Ref:'));
|
||||
}
|
||||
return [];
|
||||
}));
|
||||
|
||||
// Returns the array of columns added to the multiselect. Used as a helper to create a synced KoArray.
|
||||
var _addedObs = this.autoDispose(ko.computed(() => {
|
||||
return this.isForeignRefCol() && this.fieldObs() ?
|
||||
this._getReferencedCols().map(c => ({ label: c.label(), value: c.colId() })) : [];
|
||||
}));
|
||||
|
||||
// KoArray of columns displaying data from the referenced table in the current section.
|
||||
this._added = this.autoDispose(koArray.syncedKoArray(_addedObs));
|
||||
|
||||
// Set of added colIds.
|
||||
this._addedSet = this.autoDispose(ko.computed(() => new Set(this._added.all().map(item => item.value))));
|
||||
}
|
||||
dispose.makeDisposable(RefSelect);
|
||||
|
||||
|
||||
/**
|
||||
* Builds the multiselect dom to select columns to added to the table to show data from the
|
||||
* referenced table.
|
||||
*/
|
||||
RefSelect.prototype.buildDom = function() {
|
||||
return cssFieldList(
|
||||
testId('ref-select'),
|
||||
dom.forEach(fromKo(this._added), (col) =>
|
||||
cssFieldEntry(
|
||||
cssFieldLabel(dom.text(col.label)),
|
||||
cssRemoveIcon('Remove',
|
||||
dom.on('click', () => this._removeFormulaField(col)),
|
||||
testId('ref-select-remove'),
|
||||
),
|
||||
testId('ref-select-item'),
|
||||
)
|
||||
),
|
||||
cssAddLink(cssAddIcon('Plus'), 'Add Column',
|
||||
menu(() => [
|
||||
...this._validCols.peek()
|
||||
.filter((col) => !this._addedSet.peek().has(col.colId.peek()))
|
||||
.map((col) =>
|
||||
menuItem(() => this._addFormulaField({label: col.label(), value: col.colId()}),
|
||||
col.label.peek())
|
||||
),
|
||||
cssEmptyMenuText("No columns to add"),
|
||||
testId('ref-select-menu'),
|
||||
]),
|
||||
testId('ref-select-add'),
|
||||
),
|
||||
);
|
||||
};
|
||||
|
||||
const cssFieldList = styled('div', `
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
|
||||
& > .${cssFieldEntry.className} {
|
||||
margin: 2px 0;
|
||||
}
|
||||
`);
|
||||
|
||||
const cssEmptyMenuText = styled(menuText, `
|
||||
font-size: inherit;
|
||||
&:not(:first-child) {
|
||||
display: none;
|
||||
}
|
||||
`);
|
||||
|
||||
const cssAddLink = styled('div', `
|
||||
display: flex;
|
||||
cursor: pointer;
|
||||
color: ${colors.lightGreen};
|
||||
--icon-color: ${colors.lightGreen};
|
||||
|
||||
&:not(:first-child) {
|
||||
margin-top: 8px;
|
||||
}
|
||||
&:hover, &:focus, &:active {
|
||||
color: ${colors.darkGreen};
|
||||
--icon-color: ${colors.darkGreen};
|
||||
}
|
||||
`);
|
||||
|
||||
const cssAddIcon = styled(icon, `
|
||||
margin-right: 4px;
|
||||
`);
|
||||
|
||||
const cssRemoveIcon = styled(icon, `
|
||||
display: none;
|
||||
cursor: pointer;
|
||||
flex: none;
|
||||
margin-left: 8px;
|
||||
.${cssFieldEntry.className}:hover & {
|
||||
display: block;
|
||||
}
|
||||
`);
|
||||
|
||||
/**
|
||||
* Adds the column item to the multiselect. If the visibleCol is 'id', sets the visibleCol.
|
||||
* Otherwise, adds a field which refers to the column to the table. If a column with the
|
||||
* necessary formula exists, only adds a field to this section, otherwise adds the necessary
|
||||
* column and field.
|
||||
*/
|
||||
RefSelect.prototype._addFormulaField = function(item) {
|
||||
var field = this.fieldObs();
|
||||
var tableData = this.docModel.dataTables[this.origColumn.table().tableId()].tableData;
|
||||
// Check if column already exists in the table
|
||||
var cols = this.origColumn.table().columns().all();
|
||||
var colMatch = cols.find(c => c.formula() === `$${this.colId()}.${item.value}` && !c.isHiddenCol());
|
||||
// Get field position, so that the new field is inserted just after the current field.
|
||||
var fields = field.viewSection().viewFields();
|
||||
var index = fields.all()
|
||||
.sort((a, b) => a.parentPos() > b.parentPos() ? a : b)
|
||||
.findIndex(f => f.getRowId() === field.getRowId());
|
||||
var pos = tableUtil.fieldInsertPositions(fields, index + 1)[0];
|
||||
var colAction;
|
||||
if (colMatch) {
|
||||
// If column exists, use it.
|
||||
colAction = Promise.resolve({ colRef: colMatch.getRowId(), colId: colMatch.colId() });
|
||||
} else {
|
||||
// If column doesn't exist, add it (without fields).
|
||||
colAction = tableData.sendTableAction(['AddHiddenColumn', `${this.colId()}_${item.value}`, {
|
||||
type: 'Any',
|
||||
isFormula: true,
|
||||
formula: `$${this.colId()}.${item.value}`,
|
||||
_position: pos
|
||||
}]);
|
||||
}
|
||||
return colAction.then(colInfo => {
|
||||
// Add field to the current section.
|
||||
var fieldInfo = {
|
||||
colRef: colInfo.colRef,
|
||||
parentId: field.viewSection().getRowId(),
|
||||
parentPos: pos
|
||||
};
|
||||
return this.docModel.viewFields.sendTableAction(['AddRecord', null, fieldInfo]);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes the column item from the multiselect. If the item is the visibleCol, clears to show
|
||||
* row id. Otherwise, removes all fields which refer to the column from the table.
|
||||
*/
|
||||
RefSelect.prototype._removeFormulaField = function(item) {
|
||||
var tableData = this.docModel.dataTables[this.origColumn.table().tableId()].tableData;
|
||||
// Iterate through all display fields in the current section.
|
||||
this._getReferrerFields(item.value).forEach(refField => {
|
||||
var sectionId = this.fieldObs().viewSection().getRowId();
|
||||
if (_.any(refField.column().viewFields().all(), field => field.parentId() !== sectionId)) {
|
||||
// The col has fields in other sections, remove only the fields in this section.
|
||||
this.docModel.viewFields.sendTableAction(['RemoveRecord', refField.getRowId()]);
|
||||
} else {
|
||||
// The col is only displayed in this section, remove the column.
|
||||
tableData.sendTableAction(['RemoveColumn', refField.column().colId()]);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a list of fields in the current section whose formulas refer to 'colId' in the table this
|
||||
* reference column refers to.
|
||||
*/
|
||||
RefSelect.prototype._getReferrerFields = function(colId) {
|
||||
var re = new RegExp("^\\$" + this.colId() + "\\." + colId + "$");
|
||||
return this.fieldObs().viewSection().viewFields().all()
|
||||
.filter(field => re.exec(field.column().formula()));
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a non-repeating list of columns in the referenced table referred to by fields in
|
||||
* the current section.
|
||||
*/
|
||||
RefSelect.prototype._getReferencedCols = function() {
|
||||
var matchesSet = this._getFormulaMatchSet();
|
||||
return this._validCols().filter(c => matchesSet.has(c.colId()));
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper function for getReferencedCols. Iterates through fields in
|
||||
* the current section, returning a set of colIds which those fields' formulas refer to.
|
||||
*/
|
||||
RefSelect.prototype._getFormulaMatchSet = function() {
|
||||
var fields = this.fieldObs().viewSection().viewFields().all();
|
||||
var re = new RegExp("^\\$" + this.colId() + "\\.(\\w+)$");
|
||||
return new Set(fields.map(field => {
|
||||
var found = re.exec(field.column().formula());
|
||||
return found ? found[1] : null;
|
||||
}));
|
||||
};
|
||||
|
||||
module.exports = RefSelect;
|
257
app/client/components/RefSelect.ts
Normal file
257
app/client/components/RefSelect.ts
Normal file
@ -0,0 +1,257 @@
|
||||
import {KoArray} from 'app/client/lib/koArray';
|
||||
import * as koArray from 'app/client/lib/koArray';
|
||||
import * as tableUtil from 'app/client/lib/tableUtil';
|
||||
import {ColumnRec, DocModel, ViewFieldRec} from 'app/client/models/DocModel';
|
||||
import {KoSaveableObservable} from 'app/client/models/modelUtil';
|
||||
import {cssFieldEntry, cssFieldLabel} from 'app/client/ui/VisibleFieldsConfig';
|
||||
import {colors, testId} from 'app/client/ui2018/cssVars';
|
||||
import {icon} from 'app/client/ui2018/icons';
|
||||
import {menuText} from 'app/client/ui2018/menus';
|
||||
import {FieldBuilder} from 'app/client/widgets/FieldBuilder';
|
||||
import * as gutil from 'app/common/gutil';
|
||||
import {Disposable, dom, fromKo, styled} from 'grainjs';
|
||||
import ko from 'knockout';
|
||||
import {menu, menuItem} from 'popweasel';
|
||||
|
||||
interface Item {
|
||||
label: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder for the reference display multiselect.
|
||||
*/
|
||||
export class RefSelect extends Disposable {
|
||||
public isForeignRefCol: ko.Computed<boolean>;
|
||||
private _docModel: DocModel;
|
||||
private _origColumn: ColumnRec;
|
||||
private _colId: KoSaveableObservable<string>;
|
||||
private _fieldObs: ko.Computed<ViewFieldRec | null>;
|
||||
private _validCols: ko.Computed<ColumnRec[]>;
|
||||
private _added: KoArray<Item>;
|
||||
private _addedSet: ko.Computed<Set<string>>;
|
||||
|
||||
constructor(options: {
|
||||
docModel: DocModel,
|
||||
origColumn: ColumnRec,
|
||||
fieldBuilder: ko.Computed<FieldBuilder | null>,
|
||||
}) {
|
||||
super();
|
||||
this._docModel = options.docModel;
|
||||
this._origColumn = options.origColumn;
|
||||
this._colId = this._origColumn.colId;
|
||||
|
||||
// Indicates whether this is a ref col that references a different table.
|
||||
// (That's the only time when RefSelect is offered.)
|
||||
this.isForeignRefCol = this.autoDispose(ko.computed(() => {
|
||||
const t = this._origColumn.refTable();
|
||||
return Boolean(t && t.getRowId() !== this._origColumn.parentId());
|
||||
}));
|
||||
|
||||
// Computed for the current fieldBuilder's field, if it exists.
|
||||
this._fieldObs = this.autoDispose(ko.computed(() => {
|
||||
const builder = options.fieldBuilder();
|
||||
return builder ? builder.field : null;
|
||||
}));
|
||||
|
||||
// List of valid cols in the currently referenced table.
|
||||
this._validCols = this.autoDispose(ko.computed(() => {
|
||||
const refTable = this._origColumn.refTable();
|
||||
if (refTable) {
|
||||
return refTable.columns().all().filter(col => !col.isHiddenCol() &&
|
||||
!gutil.startsWith(col.type(), 'Ref:'));
|
||||
}
|
||||
return [];
|
||||
}));
|
||||
|
||||
// Returns the array of columns added to the multiselect. Used as a helper to create a synced KoArray.
|
||||
const _addedObs = this.autoDispose(ko.computed(() => {
|
||||
return this.isForeignRefCol() && this._fieldObs() ?
|
||||
this._getReferencedCols(this._fieldObs()!).map(c => ({ label: c.label(), value: c.colId() })) : [];
|
||||
}));
|
||||
|
||||
// KoArray of columns displaying data from the referenced table in the current section.
|
||||
this._added = this.autoDispose(koArray.syncedKoArray(_addedObs));
|
||||
|
||||
// Set of added colIds.
|
||||
this._addedSet = this.autoDispose(ko.computed(() => new Set(this._added.all().map(item => item.value))));
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the multiselect dom to select columns to added to the table to show data from the
|
||||
* referenced table.
|
||||
*/
|
||||
public buildDom() {
|
||||
return cssFieldList(
|
||||
testId('ref-select'),
|
||||
dom.forEach(fromKo(this._added.getObservable()), (col) =>
|
||||
cssFieldEntry(
|
||||
cssFieldLabel(dom.text(col.label)),
|
||||
cssRemoveIcon('Remove',
|
||||
dom.on('click', () => this._removeFormulaField(col)),
|
||||
testId('ref-select-remove'),
|
||||
),
|
||||
testId('ref-select-item'),
|
||||
)
|
||||
),
|
||||
cssAddLink(cssAddIcon('Plus'), 'Add Column',
|
||||
menu(() => [
|
||||
...this._validCols.peek()
|
||||
.filter((col) => !this._addedSet.peek().has(col.colId.peek()))
|
||||
.map((col) =>
|
||||
menuItem(() => this._addFormulaField({ label: col.label(), value: col.colId() }),
|
||||
col.label.peek())
|
||||
),
|
||||
cssEmptyMenuText("No columns to add"),
|
||||
testId('ref-select-menu'),
|
||||
]),
|
||||
testId('ref-select-add'),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the column item to the multiselect. If the visibleCol is 'id', sets the visibleCol.
|
||||
* Otherwise, adds a field which refers to the column to the table. If a column with the
|
||||
* necessary formula exists, only adds a field to this section, otherwise adds the necessary
|
||||
* column and field.
|
||||
*/
|
||||
private async _addFormulaField(item: Item) {
|
||||
const field = this._fieldObs();
|
||||
if (!field) {
|
||||
return;
|
||||
}
|
||||
const tableData = this._docModel.dataTables[this._origColumn.table().tableId()].tableData;
|
||||
// Check if column already exists in the table
|
||||
const cols = this._origColumn.table().columns().all();
|
||||
const colMatch = cols.find(c => c.formula() === `$${this._colId()}.${item.value}` && !c.isHiddenCol());
|
||||
// Get field position, so that the new field is inserted just after the current field.
|
||||
const fields = field.viewSection().viewFields();
|
||||
const index = fields.all()
|
||||
.sort((a, b) => a.parentPos() > b.parentPos() ? 1 : -1)
|
||||
.findIndex(f => f.getRowId() === field.getRowId());
|
||||
const pos = tableUtil.fieldInsertPositions(fields, index + 1)[0];
|
||||
let colAction: Promise<any>|undefined;
|
||||
if (colMatch) {
|
||||
// If column exists, use it.
|
||||
colAction = Promise.resolve({ colRef: colMatch.getRowId(), colId: colMatch.colId() });
|
||||
} else {
|
||||
// If column doesn't exist, add it (without fields).
|
||||
colAction = tableData.sendTableAction(['AddColumn', `${this._colId()}_${item.value}`, {
|
||||
type: 'Any',
|
||||
isFormula: true,
|
||||
formula: `$${this._colId()}.${item.value}`,
|
||||
_position: pos
|
||||
}])!;
|
||||
}
|
||||
const colInfo = await colAction;
|
||||
// Add field to the current section (if it isn't a raw data section - as this one will have
|
||||
// this field already)
|
||||
if (field.viewSection().isRaw()) { return; }
|
||||
const fieldInfo = {
|
||||
colRef: colInfo.colRef,
|
||||
parentId: field.viewSection().getRowId(),
|
||||
parentPos: pos
|
||||
};
|
||||
return this._docModel.viewFields.sendTableAction(['AddRecord', null, fieldInfo]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the column item from the multiselect. If the item is the visibleCol, clears to show
|
||||
* row id. Otherwise, removes all fields which refer to the column from the table.
|
||||
*/
|
||||
private _removeFormulaField(item: Item) {
|
||||
const tableData = this._docModel.dataTables[this._origColumn.table().tableId()].tableData;
|
||||
// Iterate through all display fields in the current section.
|
||||
this._getReferrerFields(item.value).forEach(refField => {
|
||||
const sectionId = this._fieldObs()!.viewSection().getRowId();
|
||||
if (refField.column().viewFields().all()
|
||||
.filter(field => !field.viewSection().isRaw())
|
||||
.some(field => field.parentId() !== sectionId)) {
|
||||
// The col has fields in other sections, remove only the fields in this section.
|
||||
return this._docModel.viewFields.sendTableAction(['RemoveRecord', refField.getRowId()]);
|
||||
} else {
|
||||
// The col is only displayed in this section, remove the column.
|
||||
return tableData.sendTableAction(['RemoveColumn', refField.column().colId()]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of fields in the current section whose formulas refer to 'colId' in the table this
|
||||
* reference column refers to.
|
||||
*/
|
||||
private _getReferrerFields(colId: string) {
|
||||
const re = new RegExp("^\\$" + this._colId() + "\\." + colId + "$");
|
||||
return this._fieldObs()!.viewSection().viewFields().all()
|
||||
.filter(field => re.exec(field.column().formula()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a non-repeating list of columns in the referenced table referred to by fields in
|
||||
* the current section.
|
||||
*/
|
||||
private _getReferencedCols(field: ViewFieldRec) {
|
||||
const matchesSet = this._getFormulaMatchSet(field);
|
||||
return this._validCols().filter(c => matchesSet.has(c.colId()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function for getReferencedCols. Iterates through fields in
|
||||
* the current section, returning a set of colIds which those fields' formulas refer to.
|
||||
*/
|
||||
private _getFormulaMatchSet(field: ViewFieldRec) {
|
||||
const fields = field.viewSection().viewFields().all();
|
||||
const re = new RegExp("^\\$" + this._colId() + "\\.(\\w+)$");
|
||||
return new Set(fields.map(f => {
|
||||
const found = re.exec(f.column().formula());
|
||||
return found ? found[1] : null;
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
const cssFieldList = styled('div', `
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
|
||||
& > .${cssFieldEntry.className} {
|
||||
margin: 2px 0;
|
||||
}
|
||||
`);
|
||||
|
||||
const cssEmptyMenuText = styled(menuText, `
|
||||
font-size: inherit;
|
||||
&:not(:first-child) {
|
||||
display: none;
|
||||
}
|
||||
`);
|
||||
|
||||
const cssAddLink = styled('div', `
|
||||
display: flex;
|
||||
cursor: pointer;
|
||||
color: ${colors.lightGreen};
|
||||
--icon-color: ${colors.lightGreen};
|
||||
|
||||
&:not(:first-child) {
|
||||
margin-top: 8px;
|
||||
}
|
||||
&:hover, &:focus, &:active {
|
||||
color: ${colors.darkGreen};
|
||||
--icon-color: ${colors.darkGreen};
|
||||
}
|
||||
`);
|
||||
|
||||
const cssAddIcon = styled(icon, `
|
||||
margin-right: 4px;
|
||||
`);
|
||||
|
||||
const cssRemoveIcon = styled(icon, `
|
||||
display: none;
|
||||
cursor: pointer;
|
||||
flex: none;
|
||||
margin-left: 8px;
|
||||
.${cssFieldEntry.className}:hover & {
|
||||
display: block;
|
||||
}
|
||||
`);
|
20
app/client/declarations.d.ts
vendored
20
app/client/declarations.d.ts
vendored
@ -76,26 +76,6 @@ declare module "app/client/components/BaseView" {
|
||||
export = BaseView;
|
||||
}
|
||||
|
||||
declare module "app/client/components/RefSelect" {
|
||||
import {Disposable} from 'app/client/lib/dispose';
|
||||
import {ColumnRec} from "app/client/models/DocModel";
|
||||
import {DocModel} from "app/client/models/DocModel";
|
||||
import {FieldBuilder} from "app/client/widgets/FieldBuilder";
|
||||
|
||||
namespace RefSelect {}
|
||||
class RefSelect extends Disposable {
|
||||
public isForeignRefCol: ko.Computed<boolean>;
|
||||
|
||||
constructor(options: {
|
||||
docModel: DocModel,
|
||||
origColumn: ColumnRec,
|
||||
fieldBuilder: ko.Computed<FieldBuilder|null>,
|
||||
});
|
||||
public buildDom(): HTMLElement;
|
||||
}
|
||||
export = RefSelect;
|
||||
}
|
||||
|
||||
declare module "app/client/components/ViewConfigTab" {
|
||||
import {GristDoc} from 'app/client/components/GristDoc';
|
||||
import {Disposable} from 'app/client/lib/dispose';
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
import * as commands from 'app/client/components/commands';
|
||||
import {GristDoc, IExtraTool, TabContent} from 'app/client/components/GristDoc';
|
||||
import RefSelect from 'app/client/components/RefSelect';
|
||||
import {RefSelect} from 'app/client/components/RefSelect';
|
||||
import ViewConfigTab from 'app/client/components/ViewConfigTab';
|
||||
import {domAsync} from 'app/client/lib/domAsync';
|
||||
import * as imports from 'app/client/lib/imports';
|
||||
@ -194,7 +194,7 @@ export class RightPanel extends Disposable {
|
||||
const isColumnValid = owner.autoDispose(ko.computed(() => Boolean(origColRef())));
|
||||
|
||||
// Builder for the reference display column multiselect.
|
||||
const refSelect = owner.autoDispose(RefSelect.create({docModel, origColumn, fieldBuilder}));
|
||||
const refSelect = RefSelect.create(owner, {docModel, origColumn, fieldBuilder});
|
||||
|
||||
// build cursor position observable
|
||||
const cursor = owner.autoDispose(ko.computed(() => {
|
||||
|
Loading…
Reference in New Issue
Block a user