Content projection issue


#1

I am doing content project on a custom element that doesn’t work when the element is composed dynamically on the view. I don’t think I’m up against the limitation of the slot

Here is my custom element ‘custom-container’

<template>
  <div class="ux-dialog-body" id="ux-dialog-body" css="width: ${width}px; height: ${height}px;" style="overflow:auto; padding:5px;">
    <slot name="body">
    </slot>
  </div>

  <slot name="footer">
    <button id="dgCancel" if.bind="cancelButtonVisible" disabled.bind="cancelDisabled" click.trigger="cancel()" class="btn btn-default"
      type="button">${cancelText}
      <b if.bind="autoCloseCancels && count">${countdown}</b>
    </button>
    <button id="dgOk" disabled.bind="okDisabled" click.trigger="ok()" type="submit" class="btn btn-primary">
      ${okText} <b if.bind="!autoCloseCancels && count">${countdown}</b>
    </button>
  </slot>
</template>

If i place this element on a view like this , I’ll get the slots doing what I expect, in this case I get the footer slot fallback content

  <custom-container>
    <div slot="body" class="form-group">
      <label for="nameField">Name</label>
      <input class="form-control" value.bind="dialogModel.model.name" type="text" id="nameField" />
    </div>
  </custom-container>

But when I have this element added to the main view dynamically by compose on thew view or compose from the view model, the projection is broken. Obviously there is an issue with compose Or i’m doing something wrong. I added an if.bind to my case where I had the custom-container in the view and kept it hidden for 5 seconds before showing it and it works fine that way. Why is compose different?


#2

Can you give an example of how you are composing?


#3

Apparently I didn’t push my commits last night so I can’t give pasted code, but I’m not doing anything fancy with compose. I tried it in the view doing <compose if.bind="myTest" view-model="myViewModel"></compose>

I also tried it the way I want it to work which is doing the compose via the container viewmodel. Both result in the same output. The settimeout was the last thing I tried thinking it was some sort of timing issue.

 bodyChanged() {
        if (this.model.type === DialogType.custom) {
            let context = this.createContext((<CustomModel>this.model).bodyViewModel, this.body, (<CustomModel>this.model).model);
            let _this = this;
            setTimeout(() => {
                _this.compositionEngine.compose(context).then((view: any) => {
                    _this.viewRef = view.viewModel;                  
                });
            }, 2000);

        }
    }

    createContext(viewModel: object, host: Element, model: object): CompositionContext {
        return {
            container: this.container.createChild(),
            viewModel: viewModel,
            model: { dialogContainer: this, model: model },
            host: host,
            bindingContext: null,
            viewResources: null,
            viewSlot: new ViewSlot(host, true)
        };
    }

The view I’m doing this compose on is the view that is bound to aurelia-dialog if that has anything to do with it. I just find it strange that when I place the contents of the view I want to compose directly in the dialog view (see first post) it works just fine even if I do the delay with the if.bind


#4

Is there anything else I can do, giving my code right now isn’t an option


#5

I just need to see the difference in behavior. From your code snippets, I can try to guess, but I was a bit confused, as it seems to be matching how current aurelia dialog default resources work. Maybe I should read what you described a bit more closely


#6

Part of that was my fault, I forgot to add the real code. Sorry. If there is no way to make this work, i’m not going to lose sleep over it because I have a working solution, it just requires me to have a separate footer viewmodel when I want different buttons


#7

I think i get what you want to do. Let me have a test and I’ll get back to you.