A multi window layout manager for webapps
DragSources work in this release.
Caution: Breaking changes 1.
newComponent()and
addComponent()type functions in
LayoutManager,
Stackand
RowOrColumnhave a new
titleparameter. This parameter is optional however it is not the last optional parameter. 1.
LayoutManager.createDragSource()has been renamed to
LayoutManager.newDragSource(). This is to make it more obvious that it is paired with
LayoutManager.removeDragSource()1.
LayoutManager.newDragSource()now only will create a ComponentItem. Its parameters have been changed to reflect that. 1. TypeScript definition has been updated to remove many private declarations which should not have been included.
Note that
LayoutManager.newDragSource()does not require
LayoutConfig.settings.constrainDragToContainerto be set to false.
Version 2.0 is now available from NPM.
This version is a substantial change from the previous (1.5.9) version. The change can be summarised as:
Before migrating from version 1, it is important to review the following:
As part of the port, the code base was significantly refactored. A number of features have been dropped from the version 1.0 as their implementation was not robust enough to meet the reliability requirements of version 2. The dropped features are:
internalor
public. Only
publicAPIs are generally available to applications.
Some features have been ported to TypeScript but are not yet ready for production. These features are:
The Version 1 to Version 2 migration guide is available here.
Version 2 examples are presented here.
Golden Layout is shipped via NPM. Use the following commands to install it into an application package:\
npm i golden-layout
The source can be installed by cloning the repository at:\
https://github.com/golden-layout/golden-layout
To build the distribution locally, open a shell at the golden-layout directory/folder and run the following commands: 1.
npm installor
npm ci(recommended) to install required dependencies 1.
npm run buildto generate the distribution (
distsubfolder). This script will: * delete the existing
liband
distfolders * compile the TypeScript code * generate the rolled up TypeScript definition files (
index.d.tsand
golden-layout-untrimmed.d.ts) * generate source map * copy the style files to the
distfolder
Note that the
libsubfolder only holds the TypeScript declaration files generated by the compiler. Generally this subfolder can be ignored. It is used during the build process to generate the rolled up TypeScript definition files.
After installing the source and building the distribution, you can build and start the
apitest(demo) app to view the library in action. Use the following commands: *
npm run apitest:buildto just build it *
npm run apitest:serveto both build and start the development server.\ You can then view it in your browser using the following link:\ http://localhost:3000/
The
apitestapp can be used to debug the Golden Layout library. Its
webpackconfiguration will import the Golden Layout library source map, allowing debuggers to step through the library source code and place break points.
If you wish to test the library with other applications, you can link to the Golden Layout repository without having to install it into the application from NPM. This is done with the
npm linkcommand. Use the following steps: 1. Make sure that the
golden-layoutpackage is not included as a dependency in the application's package 1. Run the
npm linkfrom a shell in the golden-layout source repository top level folder. 1. Run
npm link golden-layoutfrom a shell in your application's top level folder.
Your application will then use the distribution in the Golden Layout repository
distsubfolder. If you wish to make changes to the Golden Layout library, you will need to run the
build:apito regenerate the
distfolder.
A sample Angular application using Golden Layout is available. More details are here.
Version 2 has been re-written in TypeScript. A general code cleanup has been carried out as part of this re-write.
Also, some changes have been made to the GoldenLayout API. Where possible, backwards compatibility has been retained,however functions and properties kept for backwards compatibility have been marked as deprecated. It is strongly recommend applications be migrated to the new API.
The API changes include 2 new events to support creation of components:
getComponentEventand
releaseComponentEvent. With these events, it is far easier to integrate GoldenLayout into frameworks. This example application demonstrates how to integrate GoldenLayout into Angular: https://github.com/golden-layout/golden-layout-ng-app
Configs are now strongly typed. In addition, GoldenLayout now has "Configs" and "Resolved Configs" 1. Configs\ Application developers will mainly work with "Configs". A "Config" supports optional properties. If a property is not specified, a default will be used. In addition, "Config" also will handle backwards compatibility. It will migrate deprecated properties to their new values.\ Config parameters in GoldenLayout API methods will be of type "Config". The one exception is
LayoutConfig.saveLayout()which returns a "Resolved Config". 1. Resolved Configs\ Golden-Layout internally uses "Resolved Config"s. Whenever an API function is passed a "Config", GoldenLayout will resolve it to its corresponding "Resolved Config". This resolving process will set default values where an optional value has not been specified. It will also handle backwards compatibility. This allows the GoldenLayout library to always work with fully configured Configs.
For persistence of configs, always save the "Resolved Config" returned by
LayoutManager.saveLayout(). When reloading a saved Layout, first convert the saved "Resolved Config" to a "Config" by calling
LayoutConfig.fromResolved().
Both "Resolved Config" and "Config" have 2 types of interface hierarchies: 1.
ItemConfig\ This specifies the config for a content item. 1.
LayoutConfig(previously the
Configinterface)\ This specifies the config for a layout.
The (optional)
ItemConfig.idproperty now has type
string(instead of its previous
string | string[]type). For backwards compatibility, when
ItemConfig.idis resolved, it will still accept an
idwith of type string array. This will allow handling of legacy saved configs in which
idcontains an array of strings (including possibly the legacy maximise indicator). When such an
idis resolved, the array is first checked for the legacy maximise indicator and then the first element becomes the
idstring value. The remaining elements are discarded.
The
ComponentItemConfig.componentNameproperty has now been replaced by property
ComponentItemConfig.componentType.
componentTypeis of type
JsonValue. While a component type can now be specified by values that can be serialised by JSON,
componentTypemust be of type
stringif it is registered with one of the following functions: 1.
LayoutManager.registerComponent()(deprecated) 1.
LayoutManager.registerComponentConstructor()1.
LayoutManager.registerComponentFactoryFunction()
A
LayoutConfighas a
rootproperty which specifies the ItemConfig of root content item of the layout.
rootis not optional and must always be specified.
The
LayoutConfig
selectionEnabledproperty has been removed. Clicking of Stack Headers can now be handled with the new
stackHeaderClickevent (which is always enabled).
ResolvedLayoutConfignow has functions to minify and unminify configurations: 1.
minifyConfig()Replaces
LayoutManager.minifyConfig()1.
unminifyConfig()Replaces
LayoutManager.unminifyConfig()
For examples of how to create LayoutConfigs, please refer to the
apitestprogram in the repository.
Many of the Config properties have been deprecated as they overlapped or were moved to more appropriate locations. Please refer to the
config.tssource file for more information about these deprecations.
GoldenLayout is now a distinct class which is a descendant of the LayoutManager class. Your application should always create an instance of this class.
The GoldenLayout constructor takes one optional parameter: the HTML element which contains the GoldenLayout instance. If this is not specified, GoldenLayout will be placed under
body.
Note that the initial Layout is no longer specified in this constructor. Instead it is loaded with
LayoutManage.loadLayout()(see below).
registerComponentConstructor()(new function)\ Same as previous
registerComponent()however only used when registering a component constructor.
registerComponentFactoryFunction(new function)\ Same as previous
registerComponent()however only used when registering a call back function (closure) for creating components.
registerComponent(). Use the new
registerComponentConstructor()or
registerComponentFactoryFunction()instead.
getComponentEvent(new event)\ Generate a component needed by GoldenLayout. The parameters specify its container and
ItemConfig. Use this event instead of
registerComponentConstructor()or
registerComponentFactoryFunctionif you want to control the disposal of the component.
releaseComponentEvent(new event)\ Use in conjunction with
getComponentEventto release/dispose any component created for GoldenLayout
init(). Call
LayoutManager.loadLayout()instead.
loadLayout()(new function)\ Will load the new layout specified in its
LayoutConfigparameter. This can also be subsequently called whenever the GoldenLayout layout is to be replaced.
saveLayout()(new function)\ Saves the current layout as a
LayoutConfig. Replaces the existing
toConfig()function.
minifyConfig()of
unminifyConfig()functions. Use the respective functions in
ResolvedLayoutConfig.
toConfig(). Call
LayoutManager.saveLayout()instead.
setSize()(new function)\ Sets the size of the GoldenLayout instance in pixels. Replaces the existing
updateSize()function.
updateSize(). Use the new
LayoutManager.setSize()instead.
rootItem(new property) Specifies the root content item of the layout (not the Ground content item).
root. This has been replaced with the internal property
groundItem. You probably want to use the new
rootIteminstead.
focusComponent()will focus the specified component item. Only one component item can have focus. If previously, another component item had focus, then it will lose focus (become blurred).
focusor
blurevents will be emitted as appropriate unless the
suppressEventparameter is set to true.
clearComponentFocus()which removes any existing component item focus. If focus is removed, a
blurevent will be emitted unless the
suppressEventparameter is set to true.
AbstractContentItemhas been renamed to
ContentItem
configproperty has been removed. Use the toConfig() method instead (as recommended in the original GoldenLayout documentation).
configproperties such as
idand
typeare now available as properties of
ContentItemor its descendants (where appropriate).
idnow has type
string. (It used to be
string | string[].)
ItemContainerhas been renamed to
ComponentContainer
Componenthas been renamed to
ComponentItem. "Component" now refers to the external component hosted inside GoldenLayout
Roothas been renamed to
GroundItemand has been marked as internal only. Applications should never access GroundItem. Note that the layout's root ContentItem is GroundItem's only child. You can access this root ContentItem with
LayoutManager.rootItem.
Stack.getActiveContentItem()and
Stack.setActiveContentItem()have been renamed to respective
Stack.getActiveComponentItem()and
Stack.setActiveComponentItem()
ContentItem.select()and
ContentItem.deselect()have been removed. Use the new
ComponentItem.focus()and
ComponentItem.blur()instead.
ComponentItem.focus()(new function) will focus the specified ComponentItem. It will also remove focus from another component item which previously had focus. Only one component item can have focus at any time. If layout focus has changed, a
focusevent will be emitted (unless suppressEvent parameter is set to true).
ComponentItem.blur()(new function) will remove focus from the specified ComponentItem. After this is called, no component item in the layout will have focus. If the component lost focus, a
blurevent will be emitted (unless suppressEvent parameter is set to true).
element(new property - replaces
getElement())\ Returns HTMLElement which hosts component
getElement(). Use the new
elementproperty instead
initialState(new getter)\ Gets the componentState of the
ComponentItemConfigused to create the contained component.
stateRequestEvent(new event)\ If set,
stateRequestEventis fired whenever GoldenLayout wants the latest state for a component. Calling
LayoutManager.saveLayout()will cause this event to be fired (if it is defined). If it is not defined, then the initial state in the ItemConfig or the latest state set in
setState()will be saved.
beforeComponentRelease(new EventEmitter event)\
beforeComponentReleaseis emitted on the container before a component is released. Components can use this event to dispose of resources.
getState()unless you are using the deprecated
setState(). Use
ComponentContainer.initialStategetter if you have migrated to the new
ComponentContainer.stateRequestEvent.
setState()has been marked as deprecated. If possible, use the new
stateRequestEventevent instead.
replaceComponent()allows you to replace a component in a container without otherwise affecting the layout.
Several properties and functions have been renamed in
header.tsand
tab.ts. Please search for "@deprecated" in these files for these changes.
undefinedis used instead of
nullfor new properties, events etc. Some internals have also been switched to use
undefinedinstead of
null. Existing properties using
nullmostly have been left as is however it is possible that some of these internal changes have affected external properties/events/methods.
For most changes, the existing functions and properties have been left in place but marked as deprecated. It is strongly recommended that applications be reworked not to use these deprecations. Bugs associated with deprecations will be given low priority (or not fixed at all). Also, deprecated aliases, methods and properties may be removed in future releases.
All API elements (classes, interfaces, functions etc) have been labelled as either
publicor
internal. Applications should only use
publicAPI elements. Internal API elements are subject to change and no consideration will be given to backwards compatibility when these are changed.
The library distribution includes 2 TypeScript declaration (typing) files: 1.
index.d.tswhich contains only public API elements. Applications should use this declaration file to access the library. 1.
golden-layout-untrimmed.d.tswhich contains all (public and internal) API elements. Use this declaration file if you wish to access any API element in the library however please take the above warning into account.
Note that the allocation of API elements to either public or internal has not been finalised. However any element used in either the
apitestapplication or the example Angular application will remain labelled as public.
An example Angular application using Golden Layout is available. The source can be installed by cloning the repository:\ https://github.com/golden-layout/golden-layout-ng-app
After installing the source, the app can be built and started with the standard build and start scripts.
The following snippets of code demonstrate how Golden Layout can be used in Vue.
import { GoldenLayout, LayoutConfig, LayoutManager } from 'golden-layout'; import { Component, createVNode, onMounted, ref, render } from 'vue';export const isClient = typeof window !== 'undefined'; export const isDocumentReady = () => isClient && document.readyState === 'complete' && document.body != null;
export function useDocumentReady(func: () => void) { onMounted(() => { console.log(isDocumentReady()); if (isDocumentReady()) func(); else document.addEventListener('readystatechange', () => isDocumentReady() && func(), { passive: true, }); }); }
export function useGoldenLayout(components: Record, config?: LayoutConfig) { const element = ref(null); const layout = ref(null); const initialized = ref(false);
const componentsTypeMap = new Map<string component>(Object.entries(components)); useDocumentReady(() => { if (element.value == null) throw new Error('Element must be set.'); const goldenLayout = new GoldenLayout(element.value); const getComponentEvent: LayoutManager.GetComponentEventHandler = (container, itemConfig) => { const { componentType } = itemConfig; if (typeof componentType !== 'string') throw new Error('Invalid component type.'); const component = componentsTypeMap.get(componentType); if (component == null) throw new Error(`Component not found: '${componentType}'`); const node = createVNode(component); render(node, container.element); }; goldenLayout.getComponentEvent = getComponentEvent; if (config != null) goldenLayout.loadLayout(config); // https://github.com/microsoft/TypeScript/issues/34933 layout.value = goldenLayout as any; initialized.value = true; }); return { element, initialized, layout };
}
const Test = defineComponent(() => It Works!);export const Layout = defineComponent(() => { const { element } = useGoldenLayout( { Test }, { root: { type: 'row', content: [ { type: 'component', componentType: 'Test', }, ], }, } ); return () =>
; });
When attaching a component, all Golden Layout does is provide the HTML Element of a container:
Container.element. Components can use this element to bind to that Golden Layout container. For example, the component's top most HTML element could be attached as a child to this container element.
The
LayoutManager.getComponentEventevent will be fired whenever a container is created and needs a component. The
LayoutManager.releaseComponentEventevent will be fired before a container is destroyed and gives the application a chance to tear-down the component.
These events can be set up in an application's start up code as shown in the example code below.
this._goldenLayout = new GoldenLayout(goldenLayoutHostElement);this._goldenLayout.getComponentEvent = (container, itemConfig) => { const component = this.createFrameworkComponent(itemConfig); // component.element is the top most HTML element in the component container.element.appendChild(component.element); this._containerMap.set(container, component); } this._goldenLayout.releaseComponentEvent = (container, component) => { // do this if you need to dispose resources const component = this._containerMap.get(container); this.disposeFrameworkComponent(component); this._containerMap.delete(container); }
Alternatively,
container.elementcould be used as the top most HTML element in the component. Example code for this could look like:
this._goldenLayout = new GoldenLayout(goldenLayoutHostElement);this._goldenLayout.getComponentEvent = (container, itemConfig) => { const component = this.createFrameworkComponent(itemConfig, container.element); this._containerMap.set(container, component); } this._goldenLayout.releaseComponentEvent = (container, component) => { // do this if you need to dispose resources const component = this._containerMap.get(container); this.disposeFrameworkComponent(component); this._containerMap.delete(container); }
Once the
LayoutManager.getComponentEventand (optionally)
LayoutManager.releaseComponentEventevents have been set up, functions that create components can be used. For example:
LayoutManager.loadLayout()
LayoutManager.addComponent()
Also note that if
LayoutManager.getComponentEventis set up, you should not register any components with the register functions:
LayoutManager.registerComponent()
LayoutManager.registerComponentConstructor()
LayoutManager.registerComponentFactoryFunction()
LayoutManager.registerComponentFunction()
LayoutManager.registerGetComponentConstructorCallback()
LayoutManager.getComponentEventis the recommended approach for binding components to Golden Layout. The above component register functions, were mainly included in Golden Layout for backwards compatibility.