@memberjunction/ng-container-directives 4.0.0 → 4.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +67 -192
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -1,23 +1,30 @@
|
|
|
1
1
|
# @memberjunction/ng-container-directives
|
|
2
2
|
|
|
3
|
-
Angular directives for container management in MemberJunction applications
|
|
3
|
+
Angular directives for container management in MemberJunction applications -- `mjContainer` for dynamic component loading via ViewContainerRef, and `mjFillContainer` for automatic element resizing to fill parent containers.
|
|
4
4
|
|
|
5
5
|
## Overview
|
|
6
6
|
|
|
7
|
-
This package provides two essential directives for
|
|
8
|
-
- **mjContainer**: Exposes a ViewContainerRef for dynamic component loading
|
|
9
|
-
- **mjFillContainer**: Automatically resizes elements to fill their parent containers with intelligent context awareness
|
|
7
|
+
This package provides two essential layout directives. `mjContainer` exposes a `ViewContainerRef` for programmatic component creation. `mjFillContainer` automatically calculates and sets element dimensions based on the parent container, with context-aware behavior that skips resizing inside grids, hidden tabs, or elements marked with `mjSkipResize`.
|
|
10
8
|
|
|
11
|
-
|
|
9
|
+
```mermaid
|
|
10
|
+
graph TD
|
|
11
|
+
A[ContainerDirectivesModule] --> B["mjContainer Directive"]
|
|
12
|
+
A --> C["mjFillContainer Directive"]
|
|
12
13
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
14
|
+
B --> B1["Exposes ViewContainerRef"]
|
|
15
|
+
B --> B2["Dynamic Component Loading"]
|
|
16
|
+
|
|
17
|
+
C --> C1["Auto Width/Height Calculation"]
|
|
18
|
+
C --> C2["Window Resize Handling
|
|
19
|
+
(dual debounce)"]
|
|
20
|
+
C --> C3["MJGlobal Manual Resize Events"]
|
|
21
|
+
C --> C4["Context-Aware Skipping
|
|
22
|
+
(grids, hidden tabs, mjSkipResize)"]
|
|
23
|
+
|
|
24
|
+
style A fill:#2d6a9f,stroke:#1a4971,color:#fff
|
|
25
|
+
style B fill:#7c5295,stroke:#563a6b,color:#fff
|
|
26
|
+
style C fill:#2d8659,stroke:#1a5c3a,color:#fff
|
|
27
|
+
```
|
|
21
28
|
|
|
22
29
|
## Installation
|
|
23
30
|
|
|
@@ -27,95 +34,72 @@ npm install @memberjunction/ng-container-directives
|
|
|
27
34
|
|
|
28
35
|
## Usage
|
|
29
36
|
|
|
30
|
-
Import the
|
|
37
|
+
### Import the Module
|
|
31
38
|
|
|
32
39
|
```typescript
|
|
33
40
|
import { ContainerDirectivesModule } from '@memberjunction/ng-container-directives';
|
|
34
41
|
|
|
35
42
|
@NgModule({
|
|
36
|
-
imports: [
|
|
37
|
-
// ...
|
|
38
|
-
ContainerDirectivesModule
|
|
39
|
-
]
|
|
43
|
+
imports: [ContainerDirectivesModule]
|
|
40
44
|
})
|
|
41
45
|
export class YourModule { }
|
|
42
46
|
```
|
|
43
47
|
|
|
44
48
|
### mjContainer
|
|
45
49
|
|
|
46
|
-
|
|
50
|
+
Exposes a `ViewContainerRef` for dynamic component loading:
|
|
47
51
|
|
|
48
52
|
```html
|
|
49
53
|
<div mjContainer></div>
|
|
50
54
|
```
|
|
51
55
|
|
|
52
|
-
In your component:
|
|
53
|
-
|
|
54
56
|
```typescript
|
|
55
|
-
import { Component, ViewChild, ViewContainerRef } from '@angular/core';
|
|
56
57
|
import { Container } from '@memberjunction/ng-container-directives';
|
|
57
58
|
|
|
58
59
|
@Component({
|
|
59
|
-
selector: 'app-
|
|
60
|
+
selector: 'app-dynamic-host',
|
|
60
61
|
template: `<div mjContainer></div>`
|
|
61
62
|
})
|
|
62
|
-
export class
|
|
63
|
+
export class DynamicHostComponent {
|
|
63
64
|
@ViewChild(Container, { static: true }) container!: Container;
|
|
64
|
-
|
|
65
|
+
|
|
65
66
|
ngOnInit() {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
// Example: Create a dynamic component
|
|
70
|
-
// const componentRef = viewContainerRef.createComponent(YourDynamicComponent);
|
|
67
|
+
const ref = this.container.viewContainerRef;
|
|
68
|
+
// ref.createComponent(YourDynamicComponent);
|
|
71
69
|
}
|
|
72
70
|
}
|
|
73
71
|
```
|
|
74
72
|
|
|
75
73
|
### mjFillContainer
|
|
76
74
|
|
|
77
|
-
|
|
75
|
+
Automatically resizes an element to fill its parent:
|
|
78
76
|
|
|
79
77
|
```html
|
|
80
|
-
<!--
|
|
78
|
+
<!-- Fills both width and height (default) -->
|
|
81
79
|
<div mjFillContainer>Content</div>
|
|
82
80
|
|
|
83
|
-
<!--
|
|
84
|
-
<div
|
|
85
|
-
mjFillContainer
|
|
86
|
-
[fillWidth]="true"
|
|
87
|
-
[fillHeight]="true"
|
|
88
|
-
[rightMargin]="10"
|
|
89
|
-
[bottomMargin]="20">
|
|
81
|
+
<!-- Custom margins -->
|
|
82
|
+
<div mjFillContainer [fillWidth]="true" [fillHeight]="true" [rightMargin]="10" [bottomMargin]="20">
|
|
90
83
|
Content with margins
|
|
91
84
|
</div>
|
|
92
85
|
|
|
93
86
|
<!-- Fill only width -->
|
|
94
|
-
<div
|
|
95
|
-
mjFillContainer
|
|
96
|
-
[fillWidth]="true"
|
|
97
|
-
[fillHeight]="false">
|
|
87
|
+
<div mjFillContainer [fillWidth]="true" [fillHeight]="false">
|
|
98
88
|
Content that fills width only
|
|
99
89
|
</div>
|
|
100
90
|
```
|
|
101
91
|
|
|
102
|
-
###
|
|
103
|
-
|
|
104
|
-
If you need to prevent the resize behavior for certain elements:
|
|
92
|
+
### Skipping Resize
|
|
105
93
|
|
|
106
94
|
```html
|
|
107
|
-
|
|
108
|
-
<div mjSkipResize>Content</div>
|
|
95
|
+
<div mjSkipResize>This element will not be resized</div>
|
|
109
96
|
```
|
|
110
97
|
|
|
111
98
|
### Manual Resize Triggering
|
|
112
99
|
|
|
113
|
-
You can trigger manual resizing using the MemberJunction global events:
|
|
114
|
-
|
|
115
100
|
```typescript
|
|
116
101
|
import { MJGlobal, MJEventType } from '@memberjunction/global';
|
|
117
102
|
|
|
118
|
-
// Trigger resize
|
|
119
103
|
MJGlobal.Instance.RaiseEvent({
|
|
120
104
|
event: MJEventType.ManualResizeRequest,
|
|
121
105
|
args: null
|
|
@@ -124,164 +108,55 @@ MJGlobal.Instance.RaiseEvent({
|
|
|
124
108
|
|
|
125
109
|
## Configuration
|
|
126
110
|
|
|
127
|
-
|
|
111
|
+
### mjFillContainer Inputs
|
|
128
112
|
|
|
129
113
|
| Property | Type | Default | Description |
|
|
130
114
|
|----------|------|---------|-------------|
|
|
131
|
-
| fillWidth | boolean | true |
|
|
132
|
-
| fillHeight | boolean | true |
|
|
133
|
-
| rightMargin | number | 0 | Right margin in pixels |
|
|
134
|
-
| bottomMargin | number | 0 | Bottom margin in pixels |
|
|
135
|
-
|
|
136
|
-
## How It Works
|
|
137
|
-
|
|
138
|
-
The `mjFillContainer` directive dynamically calculates and sets element dimensions based on its parent container:
|
|
139
|
-
|
|
140
|
-
1. **Parent container detection**: The directive identifies the nearest block-level parent element.
|
|
141
|
-
|
|
142
|
-
2. **Size calculation**:
|
|
143
|
-
- When `fillWidth` is true, it calculates the element's width based on its parent's width, accounting for the element's position within the parent and any `rightMargin`.
|
|
144
|
-
- When `fillHeight` is true, it calculates height similarly, accounting for the `bottomMargin`.
|
|
145
|
-
|
|
146
|
-
3. **Event handling**: The directive listens for:
|
|
147
|
-
- Window resize events (with two debounce times: 100ms during active resizing, 500ms after resizing completes)
|
|
148
|
-
- Custom MJ application resize events via the MJGlobal event system
|
|
149
|
-
|
|
150
|
-
4. **Context-aware behavior**: The directive automatically skips resizing under certain conditions:
|
|
151
|
-
- Elements with the `mjSkipResize` attribute (or any parent with this attribute)
|
|
152
|
-
- Elements within a grid (role="grid")
|
|
153
|
-
- Elements within hidden tabs (not currently active)
|
|
154
|
-
- Elements with hidden or not displayed parents
|
|
115
|
+
| `fillWidth` | `boolean` | `true` | Fill the parent's width |
|
|
116
|
+
| `fillHeight` | `boolean` | `true` | Fill the parent's height |
|
|
117
|
+
| `rightMargin` | `number` | `0` | Right margin in pixels |
|
|
118
|
+
| `bottomMargin` | `number` | `0` | Bottom margin in pixels |
|
|
155
119
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
### When to Use `[fillHeight]="true" [fillWidth]="false"`
|
|
159
|
-
|
|
160
|
-
- Vertical scrollable areas where you want fixed width but dynamic height
|
|
161
|
-
- Content panels that should stretch to fill available vertical space
|
|
162
|
-
- Example: Sidebar navigation that fills vertical space but has fixed width
|
|
163
|
-
|
|
164
|
-
### When to Use `[fillHeight]="false" [fillWidth]="true"`
|
|
165
|
-
|
|
166
|
-
- Horizontal elements like headers or toolbars that span full width
|
|
167
|
-
- Fixed-height components that need to adapt to different screen widths
|
|
168
|
-
- Example: Form controls that adjust width but maintain consistent height
|
|
169
|
-
|
|
170
|
-
### When to Use Both (Default)
|
|
171
|
-
|
|
172
|
-
- Main content areas that should fill the entire available space
|
|
173
|
-
- Split panels or layouts that need to adapt to window resizing
|
|
174
|
-
- Example: Dashboards, content editors, or any primary workspace area
|
|
175
|
-
|
|
176
|
-
## Performance Optimization
|
|
177
|
-
|
|
178
|
-
- **Minimize unnecessary instances**: Only apply to containers that truly need dynamic sizing
|
|
179
|
-
- **Use `mjSkipResize` appropriately**: Apply to elements that don't need resizing
|
|
180
|
-
- **Consider debouncing**: The directive already implements debouncing, but be aware of performance impact with many instances
|
|
181
|
-
|
|
182
|
-
## Nested Containers
|
|
183
|
-
|
|
184
|
-
When nesting components with `mjFillContainer`:
|
|
185
|
-
|
|
186
|
-
1. The parent container should have the directive applied with appropriate settings
|
|
187
|
-
2. Child elements inherit the size constraints of their parents
|
|
188
|
-
3. Adjustments are calculated top-down, so parent resizing triggers child resizing
|
|
189
|
-
4. Example:
|
|
190
|
-
|
|
191
|
-
```html
|
|
192
|
-
<div mjFillContainer [fillHeight]="true" class="main-container">
|
|
193
|
-
<div class="header" style="height: 60px;">Header</div>
|
|
194
|
-
<div mjFillContainer [fillHeight]="true" class="content-area">
|
|
195
|
-
<!-- This will fill the remaining height after the header -->
|
|
196
|
-
Content
|
|
197
|
-
</div>
|
|
198
|
-
</div>
|
|
199
|
-
```
|
|
200
|
-
|
|
201
|
-
## Dependencies
|
|
202
|
-
|
|
203
|
-
This package depends on:
|
|
204
|
-
- `@memberjunction/core` - Core MemberJunction utilities and logging
|
|
205
|
-
- `@memberjunction/global` - Global event system for manual resize triggers
|
|
206
|
-
- `rxjs` - For event handling and debouncing
|
|
207
|
-
|
|
208
|
-
Peer dependencies:
|
|
209
|
-
- `@angular/common` ^18.0.2
|
|
210
|
-
- `@angular/core` ^18.0.2
|
|
211
|
-
- `@angular/router` ^18.0.2
|
|
212
|
-
|
|
213
|
-
## Troubleshooting
|
|
214
|
-
|
|
215
|
-
### Element not resizing properly
|
|
216
|
-
|
|
217
|
-
- Check if any parent has `mjSkipResize` attribute
|
|
218
|
-
- Verify the element isn't within a grid (role="grid") or hidden tab
|
|
219
|
-
- Ensure parent elements have proper CSS display properties (must be 'block')
|
|
220
|
-
- Check z-index and overflow settings
|
|
221
|
-
- Verify parent visibility (elements with hidden or not displayed parents are skipped)
|
|
222
|
-
|
|
223
|
-
### Flickering during resize
|
|
224
|
-
|
|
225
|
-
- This is usually caused by cascading resize calculations
|
|
226
|
-
- Try applying `mjFillContainer` only where necessary
|
|
227
|
-
- Use CSS transitions for smoother visual changes
|
|
228
|
-
- Consider the dual debounce strategy (100ms during resize, 500ms after)
|
|
229
|
-
|
|
230
|
-
### Height calculation issues
|
|
231
|
-
|
|
232
|
-
- Ensure parent element has a defined height or position
|
|
233
|
-
- For full window height, apply directive to a root element
|
|
234
|
-
- Check for competing CSS that might override the directive's styles
|
|
235
|
-
- Note that padding is accounted for in calculations
|
|
236
|
-
|
|
237
|
-
## Advanced Controls
|
|
238
|
-
|
|
239
|
-
For debugging or special cases, there are static properties on the FillContainer class:
|
|
120
|
+
### Static Properties
|
|
240
121
|
|
|
241
122
|
```typescript
|
|
242
123
|
import { FillContainer } from '@memberjunction/ng-container-directives';
|
|
243
124
|
|
|
244
|
-
// Disable resize globally
|
|
125
|
+
// Disable resize globally
|
|
245
126
|
FillContainer.DisableResize = true;
|
|
246
127
|
|
|
247
|
-
// Enable
|
|
128
|
+
// Enable debug logging
|
|
248
129
|
FillContainer.OutputDebugInfo = true;
|
|
249
130
|
```
|
|
250
131
|
|
|
251
|
-
##
|
|
132
|
+
## How It Works
|
|
252
133
|
|
|
253
|
-
|
|
134
|
+
1. **Parent detection**: Identifies the nearest block-level parent element
|
|
135
|
+
2. **Size calculation**: Computes dimensions based on parent size, element position, and margins
|
|
136
|
+
3. **Event handling**: Listens for window resize (dual debounce: 100ms active, 500ms settled) and MJGlobal manual resize events
|
|
137
|
+
4. **Context awareness**: Automatically skips elements with `mjSkipResize`, elements inside grids (`role="grid"`), hidden tabs, or hidden/undisplayed parents
|
|
254
138
|
|
|
255
|
-
|
|
256
|
-
@Directive({
|
|
257
|
-
selector: '[mjContainer]'
|
|
258
|
-
})
|
|
259
|
-
export class Container {
|
|
260
|
-
constructor(public viewContainerRef: ViewContainerRef) { }
|
|
261
|
-
}
|
|
262
|
-
```
|
|
139
|
+
## Dependencies
|
|
263
140
|
|
|
264
|
-
|
|
141
|
+
| Package | Description |
|
|
142
|
+
|---------|-------------|
|
|
143
|
+
| `@memberjunction/core` | Core utilities and logging |
|
|
144
|
+
| `@memberjunction/global` | Global event system |
|
|
145
|
+
| `rxjs` | Event handling and debouncing |
|
|
265
146
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
static OutputDebugInfo: boolean = false;
|
|
278
|
-
}
|
|
147
|
+
### Peer Dependencies
|
|
148
|
+
|
|
149
|
+
- `@angular/common` ^21.x
|
|
150
|
+
- `@angular/core` ^21.x
|
|
151
|
+
- `@angular/router` ^21.x
|
|
152
|
+
|
|
153
|
+
## Build
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
cd packages/Angular/Generic/container-directives
|
|
157
|
+
npm run build
|
|
279
158
|
```
|
|
280
159
|
|
|
281
|
-
##
|
|
160
|
+
## License
|
|
282
161
|
|
|
283
|
-
|
|
284
|
-
1. Follow the MemberJunction development guidelines
|
|
285
|
-
2. Ensure all TypeScript compiles without errors: `npm run build`
|
|
286
|
-
3. Update this README if adding new features or changing behavior
|
|
287
|
-
4. Add appropriate TSDoc comments to all public APIs
|
|
162
|
+
ISC
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@memberjunction/ng-container-directives",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.2.0",
|
|
4
4
|
"description": "MemberJunction: Angular Container Directives - Fill Container for Auto-Resizing, and plain container just for element identification/binding",
|
|
5
5
|
"main": "./dist/public-api.js",
|
|
6
6
|
"typings": "./dist/public-api.d.ts",
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
"@angular/router": "21.1.3"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@memberjunction/core": "4.
|
|
33
|
-
"@memberjunction/global": "4.
|
|
32
|
+
"@memberjunction/core": "4.2.0",
|
|
33
|
+
"@memberjunction/global": "4.2.0",
|
|
34
34
|
"rxjs": "~7.8.2",
|
|
35
35
|
"tslib": "^2.8.1"
|
|
36
36
|
},
|