Set the parent of an Aurelia Dialog - aurelia

Aurelia Dialog puts all the UI elements for itself at the root of the document (or very near).
Is there a way to configure where the dialog places itself in the document?
(I am trying to make the dialog be part of my router page rather than part of the overall document.)

Yes you can, as stated by the official doc: http://aurelia.io/hub.html#/doc/article/aurelia/dialog/latest/dialog-basics/5
In the controller settings part, there is a config property name host, which you can pass an element here to be anchor for the dialog, instead of the default document.body
doc:
host: allows providing the element which will parent the dialog - if not provided the body will be used.

Related

Does OutletService support dynamically adding component in button handler

i used this.outletService.add('BottomHeaderSlot', factory, OutletPosition.BEFORE); during the search button click handler to add a custom component in the BottomHeaderSlot. I intended to add searchOverlay under the header to add customized search behavior.
But my custom component is not shown under the header after calling outletService.add. I refered to this https://sap.github.io/cloud-commerce-spartacus-storefront-docs/outlets/ . Does outletService support dynamic adding component during runtime?
Following is my button handler
open(): void {
const factory = this.componentFactoryResolver.resolveComponentFactory<SearchOverlayComponent>(SearchOverlayComponent);
this.outletService.add('BottomHeaderSlot', <any>factory, OutletPosition.BEFORE);
this.cd.markForCheck();
That's a good question. At the moment it is a not a feature supported from our outlets.
A solution you could do is inject the component in a more static manner (either CMS or outlet when the app initializes like seen here https://github.com/SAP/cloud-commerce-spartacus-storefront/blob/develop/projects/storefrontlib/src/cms-components/asm/services/asm-enabler.service.ts)?
Your component could then be wrapped with an <ng-container *ngIf="open$ | async></ng-container> where open$ is an observable for the state of the search box. That way the component only appears in the dom when the searchbox is open.
The idea of dynamically adding a components through outlets is a good one we will keep in mind. I will open an issue on Github as an improvement.

Aurelia - dynamically create custom element in a view-model

I have an Aurelia app where a user can click on a button and create a new tab. The tab and its content (a custom element) do not exist on the page before the user clicks the button. I am generating the HTML for the content at runtime (via Javascript) in my view model.
I keep seeing mention of using the template engine's compose or enhance functions, but neither are working for me. I don't know how I would use the <compose> element (in my HTML) since I am creating the element based on the user clicking a button.
My thought was that the button has a click.delegate to a function that does ultimately does something like
const customElement = document.createElement('custom-element');
parentElement.appendChild(customElement);
const view = this.templatingEngine.enhance({
element : customElement,
container : this.container, // injected
resources : this.viewResources, // injected
bindingContext: {
attrOne: this.foo,
attrTwo: this.bar,
}
});
view.attached();
But all this does is create an HTML element <custom-element></custom-element> without actually binding any attributes to it.
How can I create a custom element analogous to <custom-element attr-one.bind="foo" attr-two.bind="bar"></custom-element> but via Javascript?
As you pointed out in your own answer, it's the missing resources that caused the issue. One solution is to register it globally. That is not always the desired behavior though, as sometimes you want to lazily load the resources and enhance some lazy piece of HTML. Enhance API accepts an option for the resources that you want to compile the view with. So you can do this:
.enhance({
resources: new ViewResources(myGlobalResources) // alter the view resources here
})
for the view resources, if you want to get it from a particular custom element, you can hook into the created lifecycle and get it, or you can inject the container and retrieve it via container.get(ViewResources)
I found the problem =\ I had to make my custom element a global resource.

Does the windowClass property or NgbModalOptions actually do anything?

I am opening an NgbModal passing a TemplateRef to create the dialog body, and passing in a custom class via the windowClass property of the NgbModalOptions object that I pass to the open() method. I define the class in a referenced styleUrl in the component and am serving the modal via an injectable service in the component. The modal is loading fine, and I can see the class name when I inspect the DOM, but the class appears to have no bearing on the modal. I would like to use it to customize the size of the modal (css is defined to affect the child div where the size is set), but I have also played with properties that I can see in the Styles tab of the Chrome dev tools, but cannot see it affecting anything. When I inspect in Firefox dev tools, I can find the CSS as an inline style sheet and it has a reference to the ngContent identifier assigned by Angular, so I am assuming that is does not affect the entire document, nor those parts added by ng-bootstrap that constitute the modal wrapper. Has anyone been able to make this work successfully? I am at my wit's end. I would even be happy if I could get an ElementRef of the modal-header dive, but since I am using a template (which is not fully loaded in the DOM at init time) I have not been able to. One of my requirements is that we do all DOM manipulation via Angular to maintain platform independence in the project ... so no jQuery. Any thoughts? And thanks in advance!!
I use windowClass and size attributes of NgbModalOptions to customize the modal. Sample code follows:
this.modalService.open(<your_template_ref_var>, {size: 'lg', windowClass: 'modal-adaptive-s1'});
Whereas
.modal-adaptive-s1 .modal-lg {width: 400px !important; max-width: 400px;}

Initialize dynamic Component in Code using Vue.js

I am currently developing a web application that is used to display elements for events on a map provided by HERE Maps. I am using Vue.
I have some components, but the relevant component is the component HereMaps.vue which initializes the map using the HERE Maps Api.
The HERE Maps Api provides the possibility to place so called InfoBubbles on the map showing additional information. These InfoBubbles can be provided some HTML-code in order to customize their appearance.
Please refer to the documentation for additional information
Following the documentation the code looks something like this:
let bubble = new H.ui.InfoBubble(marker.getPosition(), {
content: "<div class='someClass'>Some Content</div>"
});
this.ui.addBubble(bubble)
This is happening after mount in the "mounted" method from Vue in the "HereMaps" component.
The Bubbles are added in a "closed" (hidden) form and dynamically "opened" to reveal their content when the corresponding marker icon on the map is clicked. Therefore the HTML-code is present on the DOM after the component is mounted and is not removed at a later stage.
Now instead of supplying custom code within each bubble added to the UI i want to just add a component like this:
let bubble = new H.ui.InfoBubble(marker.getPosition(), {
content: "<myDynamicComponent></myDynamicComponent>"
});
this.ui.addBubble(bubble)
It does not matter to me wether the component is initialized using props or if it is conditionally rendered depending on the state of a global variable. I just want to be able to use the "myDynamicComponent" in order to customize the appearance in a different file. Otherwise the design process gets very messy.
As far as i know this is not possible or at least i was not able to get it work. This is probably due to the fact that the "myDynamicComponent" is not used within the "template" of the "HereMaps" component und thus Vue does not know that it needs to render something here after the directive is added to the DOM in the "mounted" method.
This is what the InfoBubble looks using normal HTML as an argument:
This is what the InfoBubble looks using the component as an argument:
It appears to just be empty. No content of the "myDynamicComponent" is shown.
Does anyone have any idea how i could solve this problem.
Thank You.
Answer is a bit complicated and I bet you wouldn't like it:)
content param can accept String or Node value. So you can make new Vue with rendered your component and pass root element as content param.
BTW, Vue does not work as you think, <myDynamicComponent></myDynamicComponent> bindings, etc exists in HTML only in compile time. After that all custom elements(components) are compiled to render functions. So you can't use your components in that way.
Give us fiddle with your problem, so we can provide working example:)

dijit.Menu to be displayed after DOM had been set up

I have set up in Javascript my preferred dijit.Menu which is that far so good.
How am I able to display the dijit.Menu directly after the page starts up in the (with it's position) without any mouse interaction?! I have looked in the API so far and don't find the answers. Will I have to "overwrite" a method?
If yes, which one is it? And what do I have todo???
The widget will not show up until it is parsed by dojo.
You should place fake menu markup inside its dom node:
<div dojoType="dijit.Menu">
<h1>This text is shown after the dom is loaded
and until the menu is parsed and renered</h1>
</div>
As soon as menu is ready, everything you've placed inside menu's dom node will be replaced by actual widget's html.
NON-AMD Version:
dojo.ready(function(){
// The code for all items!
})
DOJO-AMD Version, put the parameters of the modules you like to add, in require as well give them a name in the functions parameters list:
require(["dojo/domReady!"],function(){
//natve code
});