New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

create can.Component for custom tags #327

Closed
justinbmeyer opened this Issue Mar 21, 2013 · 27 comments

Comments

Projects
None yet
6 participants
@justinbmeyer
Contributor

justinbmeyer commented Mar 21, 2013

Background:

I'd like to start making it possible to create custom tags similar to webcomponents.

For example:

<overlay displayWhen="userIsLoggedIn" class="{{classHelper foo}}"><h1> Hello World</h1></overlay>

powered by something like

can.Component("Overlay", {
  template: "TEMPLATEREF",
  "{displayWhen} change": function(displayWhen, ev, display){
    display? this.element.show() : this.element.hide()
  }
})

Considerations:

Merging DOM

How to merge things setup in the "outer" template like:

  • attributes of the custom tag
  • children of the custom tag

with the tag's template?

AMD / Steal nameless modules.

@schovi

This comment has been minimized.

Show comment
Hide comment
@schovi

schovi Mar 22, 2013

Contributor

👍
Awesome idea. Still solving how effectively initialize some Controls.

Contributor

schovi commented Mar 22, 2013

👍
Awesome idea. Still solving how effectively initialize some Controls.

@justinbmeyer

This comment has been minimized.

Show comment
Hide comment
@justinbmeyer

justinbmeyer Mar 26, 2013

Contributor
can.Component("Todos",{
  init: function(element, scope){
    scope.attr('todos', [{...}, ....]
  },
  template: "<ul>{{#todos}}<li>{{name}}</li></ul>"
})
Contributor

justinbmeyer commented Mar 26, 2013

can.Component("Todos",{
  init: function(element, scope){
    scope.attr('todos', [{...}, ....]
  },
  template: "<ul>{{#todos}}<li>{{name}}</li></ul>"
})
@justinbmeyer

This comment has been minimized.

Show comment
Hide comment
@justinbmeyer

justinbmeyer Mar 26, 2013

Contributor
            can.Component("tabs",{
                    init: function(element, options){
                        options.attr('panes',[])
                    },
                    addPane: function(pane){
                        if (this.options.panes.length == 0){
                            this.options.select(pane);
                        }
                    this.options.panes.push({
                        selected: false,
                        pane: pane
                    });
                    },
                    select: function(pane){
                        can.each(this.options.panes,function(pane){
                            pane.attr('selected',false)
                        })
                    },
                    template: 
                        '<div class="tabbable">' +
                      '<ul class="nav nav-tabs">' +
                        '{{panes}}'+
                        '<li class="{{#selected}}active{{/}}">'+
                          '<a can-click="select(pane)">{{pane.title}}</a>' +
                        '</li>' +
                      '</ul>' +
                      '<div class="tab-content" can-select="*"></div>' +
                    '</div>'
            });
Contributor

justinbmeyer commented Mar 26, 2013

            can.Component("tabs",{
                    init: function(element, options){
                        options.attr('panes',[])
                    },
                    addPane: function(pane){
                        if (this.options.panes.length == 0){
                            this.options.select(pane);
                        }
                    this.options.panes.push({
                        selected: false,
                        pane: pane
                    });
                    },
                    select: function(pane){
                        can.each(this.options.panes,function(pane){
                            pane.attr('selected',false)
                        })
                    },
                    template: 
                        '<div class="tabbable">' +
                      '<ul class="nav nav-tabs">' +
                        '{{panes}}'+
                        '<li class="{{#selected}}active{{/}}">'+
                          '<a can-click="select(pane)">{{pane.title}}</a>' +
                        '</li>' +
                      '</ul>' +
                      '<div class="tab-content" can-select="*"></div>' +
                    '</div>'
            });
@matthewp

This comment has been minimized.

Show comment
Hide comment
@matthewp

matthewp May 17, 2013

Contributor

Is the goal to 1) provide some today-compatible version of web components, 2) build on top of web components 3) build something that is functionally similar (and if so, to what extent; is it only that this would be custom tag elements?)?

Contributor

matthewp commented May 17, 2013

Is the goal to 1) provide some today-compatible version of web components, 2) build on top of web components 3) build something that is functionally similar (and if so, to what extent; is it only that this would be custom tag elements?)?

@justinbmeyer

This comment has been minimized.

Show comment
Hide comment
@justinbmeyer

justinbmeyer May 17, 2013

Contributor

1 + 3.

I think at the start, there will have to be normal elements (to support IE), but with a special attribute name.

Eventually, this can run on web-component technology when it's available in all browsers. The biggest gap right now is mutation events and hooks into custom elements.

Contributor

justinbmeyer commented May 17, 2013

1 + 3.

I think at the start, there will have to be normal elements (to support IE), but with a special attribute name.

Eventually, this can run on web-component technology when it's available in all browsers. The biggest gap right now is mutation events and hooks into custom elements.

@matthewp

This comment has been minimized.

Show comment
Hide comment
@matthewp

matthewp May 17, 2013

Contributor

FWIW x-tags (Mozilla's polyfill) uses animationstart as an alternative to mutation events.

Contributor

matthewp commented May 17, 2013

FWIW x-tags (Mozilla's polyfill) uses animationstart as an alternative to mutation events.

@justinbmeyer

This comment has been minimized.

Show comment
Hide comment
@justinbmeyer

justinbmeyer May 18, 2013

Contributor

What about browsers that do not support animation events?

Sent from my iPhone

On May 17, 2013, at 5:59 PM, Matthew Phillips notifications@github.com wrote:

FWIW x-tags (Mozilla's polyfill) uses animationstart as an alternative to mutation events.


Reply to this email directly or view it on GitHub.

Contributor

justinbmeyer commented May 18, 2013

What about browsers that do not support animation events?

Sent from my iPhone

On May 17, 2013, at 5:59 PM, Matthew Phillips notifications@github.com wrote:

FWIW x-tags (Mozilla's polyfill) uses animationstart as an alternative to mutation events.


Reply to this email directly or view it on GitHub.

@matthewp

This comment has been minimized.

Show comment
Hide comment
@matthewp

matthewp May 23, 2013

Contributor

Should be able to use the old mutation events to get you to IE9. Below that it's probably not practical. I would think it's possible to overload document.createElement and htmlelement.prototype.innerhtml but no one else does that so there's probably a good reason.

The killer feature of web components is the ability to add a tag to your markup and have it just work. In my opinion sacrificing that in order to support older browsers would be a mistake. I'm not sure what the gain is over can.Control if you have to add them through JS.

Another really cool thing about web components is HTML imports which allow you to add components through the link tag. I think there is opportunity here for someone to become the NPM of web components by acting as a repository/CDN for components.

Contributor

matthewp commented May 23, 2013

Should be able to use the old mutation events to get you to IE9. Below that it's probably not practical. I would think it's possible to overload document.createElement and htmlelement.prototype.innerhtml but no one else does that so there's probably a good reason.

The killer feature of web components is the ability to add a tag to your markup and have it just work. In my opinion sacrificing that in order to support older browsers would be a mistake. I'm not sure what the gain is over can.Control if you have to add them through JS.

Another really cool thing about web components is HTML imports which allow you to add components through the link tag. I think there is opportunity here for someone to become the NPM of web components by acting as a repository/CDN for components.

@justinbmeyer

This comment has been minimized.

Show comment
Hide comment
@justinbmeyer

justinbmeyer May 23, 2013

Contributor

It will just work as long as you are using jQuery or one of the libraries helpers to insert HTML. $().append, $().html, etc. In this way we can support older browsers, and how people typically manipulate the DOM.

Also, with live binding, the amount of DOM manipulation that goes on is exceedingly minimal lately. It's almost always just:

this.element.html( can.view( ... ) )
Contributor

justinbmeyer commented May 23, 2013

It will just work as long as you are using jQuery or one of the libraries helpers to insert HTML. $().append, $().html, etc. In this way we can support older browsers, and how people typically manipulate the DOM.

Also, with live binding, the amount of DOM manipulation that goes on is exceedingly minimal lately. It's almost always just:

this.element.html( can.view( ... ) )
@justinbmeyer

This comment has been minimized.

Show comment
Hide comment
@justinbmeyer

justinbmeyer May 23, 2013

Contributor

By this, I mean, we don't really need to support document.createElement and such. We will support that directly in browsers that support it, but most people who use jQuery are accustomed to doing $().html() anyway.

I've talked with James Burke about HTML imports, I don't care for them unless you can build it. We talked about how AMD / require / steal could support loading imports.

But yes, I agree that we need an easy way to share components, but dependency management is really the key because even if web components became popular, they will still have dependencies on libraries.

Contributor

justinbmeyer commented May 23, 2013

By this, I mean, we don't really need to support document.createElement and such. We will support that directly in browsers that support it, but most people who use jQuery are accustomed to doing $().html() anyway.

I've talked with James Burke about HTML imports, I don't care for them unless you can build it. We talked about how AMD / require / steal could support loading imports.

But yes, I agree that we need an easy way to share components, but dependency management is really the key because even if web components became popular, they will still have dependencies on libraries.

@justinbmeyer

This comment has been minimized.

Show comment
Hide comment
@justinbmeyer

justinbmeyer May 23, 2013

Contributor

One more thing ... I don't think that the killer feature of can.Component will be:

the ability to add a tag to your markup and have it just work.

That's the killer feature of web-components as you correctly identified. The advantage of can.Component over can.Control is first that it hooks up 3 extremely common items of a component by convention:

  • can.Control
  • A view-model (which is currently this.options, but this.options is extremely underpowered).
  • A live-bound template

Second, it allows you to "pass" a template to a control. I need a better term for this, but consider this example:

<h2>Things</h2>
<ul can-component="List" data-model="Things">
  {{#items}}
  <li>{{name}}</li>
  {{/items}}
</ul>

The developer doesn't need to do something like this instead:

new List("ul",{
  model: Things,
  view: can.view("list-of-things")
})

The designer can see more of the structure of the page all in one place. This is very nice for basic widget-y type controls that might need a micro template from the user. The user doesn't have to define the template elsewhere.

This breaks down eventually as you want high-level components to carry their template with them. But, that's fine.

cc @shcarrico (I've talked with Stan quite a bit about this)

Contributor

justinbmeyer commented May 23, 2013

One more thing ... I don't think that the killer feature of can.Component will be:

the ability to add a tag to your markup and have it just work.

That's the killer feature of web-components as you correctly identified. The advantage of can.Component over can.Control is first that it hooks up 3 extremely common items of a component by convention:

  • can.Control
  • A view-model (which is currently this.options, but this.options is extremely underpowered).
  • A live-bound template

Second, it allows you to "pass" a template to a control. I need a better term for this, but consider this example:

<h2>Things</h2>
<ul can-component="List" data-model="Things">
  {{#items}}
  <li>{{name}}</li>
  {{/items}}
</ul>

The developer doesn't need to do something like this instead:

new List("ul",{
  model: Things,
  view: can.view("list-of-things")
})

The designer can see more of the structure of the page all in one place. This is very nice for basic widget-y type controls that might need a micro template from the user. The user doesn't have to define the template elsewhere.

This breaks down eventually as you want high-level components to carry their template with them. But, that's fine.

cc @shcarrico (I've talked with Stan quite a bit about this)

@steeleprice

This comment has been minimized.

Show comment
Hide comment
@steeleprice

steeleprice May 23, 2013

There is a great need for simplifying the instantiation and communication between Components in a standard way for current functionality. I have spent lots and lots of time architecting and re-architecting how to do this properly with CanJS.

Consider the following architecture:

App (with a component cache)

  • componentA
    • subcomponent1
    • subcomponent2
    • subcomponent3
  • componentB
    • subcomponent2

Currently I have to do this in a less than spectacular way since a "Component" is essentially Construct+Control, one or more Models, one or more templates and a css file. So this defines "Component", though it doesn't address instantiation of a component or Facade and Mediator. For Mediation between Components almost everyone using CanJS correctly recommends using Observe for this but there is no real guidance on where to put them, are they injected into Component or just Observed? We also need Facade for things like security and error management.

App has the responsibility to load Components as needed and for managing their current state (think of it as the smart component cache). App is completely ignorant of what Components are doing but it does know which ones are loaded. Hopefully, most people know Components are not the same as Plugins, Components should be ignorant of the the App and implement a Facade Pattern instead, whereas Plugins are usually extending App and know about (at least some of ) its functionality. Facade and Mediator are missing in CanJS, what's tying all these Components together?

This structure is what CanJS is currently lacking: App->Mediators->Facade->Components->(low level abstractions)
The left four are completely roll-your-own with no clear guidance about how the framework is intended to be used for this. All the low level abstractions are great and working well, adding these or offering clear guidance around how CanJS is best used in this structure will be terrific.

steeleprice commented May 23, 2013

There is a great need for simplifying the instantiation and communication between Components in a standard way for current functionality. I have spent lots and lots of time architecting and re-architecting how to do this properly with CanJS.

Consider the following architecture:

App (with a component cache)

  • componentA
    • subcomponent1
    • subcomponent2
    • subcomponent3
  • componentB
    • subcomponent2

Currently I have to do this in a less than spectacular way since a "Component" is essentially Construct+Control, one or more Models, one or more templates and a css file. So this defines "Component", though it doesn't address instantiation of a component or Facade and Mediator. For Mediation between Components almost everyone using CanJS correctly recommends using Observe for this but there is no real guidance on where to put them, are they injected into Component or just Observed? We also need Facade for things like security and error management.

App has the responsibility to load Components as needed and for managing their current state (think of it as the smart component cache). App is completely ignorant of what Components are doing but it does know which ones are loaded. Hopefully, most people know Components are not the same as Plugins, Components should be ignorant of the the App and implement a Facade Pattern instead, whereas Plugins are usually extending App and know about (at least some of ) its functionality. Facade and Mediator are missing in CanJS, what's tying all these Components together?

This structure is what CanJS is currently lacking: App->Mediators->Facade->Components->(low level abstractions)
The left four are completely roll-your-own with no clear guidance about how the framework is intended to be used for this. All the low level abstractions are great and working well, adding these or offering clear guidance around how CanJS is best used in this structure will be terrific.

@justinbmeyer

This comment has been minimized.

Show comment
Hide comment
@justinbmeyer

justinbmeyer May 23, 2013

Contributor

@steeleprice did you read my previous comment about how can.Components main feature is NOT the ability to add custom tags?

Contributor

justinbmeyer commented May 23, 2013

@steeleprice did you read my previous comment about how can.Components main feature is NOT the ability to add custom tags?

@justinbmeyer

This comment has been minimized.

Show comment
Hide comment
@justinbmeyer

justinbmeyer May 23, 2013

Contributor

@steeleprice anyway you can clean up that post a little to get more to the point. I'm not really sure what you are saying. I'll give you an example:

There is also some cross pollination here with Issue 305 if you want computes directly bound.

What does this have to do with can.Component?

Your post seems to be talking about other issues you are having and not related to this discussion.

Contributor

justinbmeyer commented May 23, 2013

@steeleprice anyway you can clean up that post a little to get more to the point. I'm not really sure what you are saying. I'll give you an example:

There is also some cross pollination here with Issue 305 if you want computes directly bound.

What does this have to do with can.Component?

Your post seems to be talking about other issues you are having and not related to this discussion.

@justinbmeyer

This comment has been minimized.

Show comment
Hide comment
@justinbmeyer

justinbmeyer May 23, 2013

Contributor

@steeleprice btw, we use steal to package components. Packaging is not something that we're looking to solve in CanJS.

Contributor

justinbmeyer commented May 23, 2013

@steeleprice btw, we use steal to package components. Packaging is not something that we're looking to solve in CanJS.

@steeleprice

This comment has been minimized.

Show comment
Hide comment
@steeleprice

steeleprice May 23, 2013

I'm looking at steal to see if it can do what I need for loading easier than RequireJS, but that really only deals with the dynamic loading part. Perhaps I am missing the idea of can.Component. I mean if you are going to make can.Component, isn't the idea of a "Component" a package of multiple parts that makes up a usable Widget? WebComponent is pretty specific and if that's what you want to support, call it that. Component is more abstract even though the draft says "Both decorators and custom elements are called components" This is horribly misleading about what the functionality truly is. Packaging is definitely part of the spec. in Part 8: "Custom elements and decorators can be loaded from external files using the link tag" so does this mean can.Component would use steal to load any imports defined in the component? We are talking about 5 pieces designed to be used together to design widgets. This is a huge issue and saying, oh... we use steal is just covering one part of a much bigger issue.

steeleprice commented May 23, 2013

I'm looking at steal to see if it can do what I need for loading easier than RequireJS, but that really only deals with the dynamic loading part. Perhaps I am missing the idea of can.Component. I mean if you are going to make can.Component, isn't the idea of a "Component" a package of multiple parts that makes up a usable Widget? WebComponent is pretty specific and if that's what you want to support, call it that. Component is more abstract even though the draft says "Both decorators and custom elements are called components" This is horribly misleading about what the functionality truly is. Packaging is definitely part of the spec. in Part 8: "Custom elements and decorators can be loaded from external files using the link tag" so does this mean can.Component would use steal to load any imports defined in the component? We are talking about 5 pieces designed to be used together to design widgets. This is a huge issue and saying, oh... we use steal is just covering one part of a much bigger issue.

@steeleprice

This comment has been minimized.

Show comment
Hide comment
@steeleprice

steeleprice May 23, 2013

I think I should move this discussion over to the https://forum.javascriptmvc.com/canjs since it's not really an issue other than defining what the functionality of can.Component really should be. There are at least 5 people on the forums trying to solve the same thing (loading, communicating between and packaging what we are all calling components) in 5 different ways.

steeleprice commented May 23, 2013

I think I should move this discussion over to the https://forum.javascriptmvc.com/canjs since it's not really an issue other than defining what the functionality of can.Component really should be. There are at least 5 people on the forums trying to solve the same thing (loading, communicating between and packaging what we are all calling components) in 5 different ways.

@justinbmeyer

This comment has been minimized.

Show comment
Hide comment
@justinbmeyer

justinbmeyer May 23, 2013

Contributor

I agree that any discussion outside the specifics of can.Component should be moved to the forums. But I want to keep this discussion it's functionality. If there are use cases you have around WebComponents, or thoughts, please write them in a forum post.

Here's the functionality of can.Component:

A merger of can.Control, an observable View-Model, and a template, that can be instantiated via custom tags (or other markup).

Think about it this way, how often do you have a can.Control like:

GroupControl = can.Control({
  init: function(){
    this.options.usersLoaded = can.compute(false)
    this.options.showUsers = can.compute(false)
    this.option.users = can.compute()
    this.element.html( INIT_TEMPLATE(this.options) )
  }
})

And how often in a parent control are you doing:

this.element.html(INIT_TEMPLATE)
new Group( this.element.find(".group"), {group: group});

I do this all the time.

I'd like to be able to do something like:

<group>
   <ul {{^showUsers}}style="display:none"{{/showUsers}} class='users'>
        {{#usersLoaded}}
            {{#users}}
                <li {{data "user"}} class='user'>{{name}} <button class='destroy'>X</button></li>
            {{/users}}
            {{^users}}
                <li>No users in group</li>
            {{/users}}
        {{/usersLoaded}}
        {{^usersLoaded}}
            <li>Loading Data</li>
        {{/usersLoaded}}
    </ul>
</group>

And have Group look more like:

can.component("group",{
  template: "<h3>{{group.name}}</h3><div class='content'><content></content>",
  "h3 click": function(){
     if( this.attr('usersLoaded') ){
        this.attr('users', new User.List({groupId: this.attr('group')}, function(){
          self.attr('usersLoaded', true)
        })
     }
     if( ! this.attr('showUsers') ){
       this.attr('showUsers', true)
     } else {
       this.attr('showUsers', false)
     }
  }
})

The special parts of this are:

  1. The group control is created automatically with this.attr(prop) having access to the current context of the template in which it was created. This is how this.attr('group') works.
  2. The template the user provided is merged automatically with the group's template.

And parts not shown:

  1. A can.component is really the view-model, so it will be like an observe, and have setters and such.
  2. Any templated event handlers like "{users} change" will be automatically updated without having to call .on().

What we are going to try to nail down is the very common practice of having a can.Control wire up its view-model and template, and how it is invoked. It's API isn't finalized, but this is the problem we are trying to solve.

Contributor

justinbmeyer commented May 23, 2013

I agree that any discussion outside the specifics of can.Component should be moved to the forums. But I want to keep this discussion it's functionality. If there are use cases you have around WebComponents, or thoughts, please write them in a forum post.

Here's the functionality of can.Component:

A merger of can.Control, an observable View-Model, and a template, that can be instantiated via custom tags (or other markup).

Think about it this way, how often do you have a can.Control like:

GroupControl = can.Control({
  init: function(){
    this.options.usersLoaded = can.compute(false)
    this.options.showUsers = can.compute(false)
    this.option.users = can.compute()
    this.element.html( INIT_TEMPLATE(this.options) )
  }
})

And how often in a parent control are you doing:

this.element.html(INIT_TEMPLATE)
new Group( this.element.find(".group"), {group: group});

I do this all the time.

I'd like to be able to do something like:

<group>
   <ul {{^showUsers}}style="display:none"{{/showUsers}} class='users'>
        {{#usersLoaded}}
            {{#users}}
                <li {{data "user"}} class='user'>{{name}} <button class='destroy'>X</button></li>
            {{/users}}
            {{^users}}
                <li>No users in group</li>
            {{/users}}
        {{/usersLoaded}}
        {{^usersLoaded}}
            <li>Loading Data</li>
        {{/usersLoaded}}
    </ul>
</group>

And have Group look more like:

can.component("group",{
  template: "<h3>{{group.name}}</h3><div class='content'><content></content>",
  "h3 click": function(){
     if( this.attr('usersLoaded') ){
        this.attr('users', new User.List({groupId: this.attr('group')}, function(){
          self.attr('usersLoaded', true)
        })
     }
     if( ! this.attr('showUsers') ){
       this.attr('showUsers', true)
     } else {
       this.attr('showUsers', false)
     }
  }
})

The special parts of this are:

  1. The group control is created automatically with this.attr(prop) having access to the current context of the template in which it was created. This is how this.attr('group') works.
  2. The template the user provided is merged automatically with the group's template.

And parts not shown:

  1. A can.component is really the view-model, so it will be like an observe, and have setters and such.
  2. Any templated event handlers like "{users} change" will be automatically updated without having to call .on().

What we are going to try to nail down is the very common practice of having a can.Control wire up its view-model and template, and how it is invoked. It's API isn't finalized, but this is the problem we are trying to solve.

@justinbmeyer

This comment has been minimized.

Show comment
Hide comment
@justinbmeyer

justinbmeyer May 23, 2013

Contributor

I mean, it might be better to break up can.component's parts to be more like how mozilla's x-tags approaches it:

can.component('group',{
  template: "the template",
  model: {
    property: "defaultValue",
    setProperty: function(){}
  },
  events: {
    "h3 click": function(){
      this.model.property
    }
  }
})
Contributor

justinbmeyer commented May 23, 2013

I mean, it might be better to break up can.component's parts to be more like how mozilla's x-tags approaches it:

can.component('group',{
  template: "the template",
  model: {
    property: "defaultValue",
    setProperty: function(){}
  },
  events: {
    "h3 click": function(){
      this.model.property
    }
  }
})
@matthewp

This comment has been minimized.

Show comment
Hide comment
@matthewp

matthewp May 23, 2013

Contributor

Why put the event functions on an events property?

Contributor

matthewp commented May 23, 2013

Why put the event functions on an events property?

@steeleprice

This comment has been minimized.

Show comment
Hide comment
@steeleprice

steeleprice May 23, 2013

Thank you very much for this great explanation. This is indeed exactly what I am trying to resolve in a better way right now with a single caveat, the large scale Application. It's Applications with High Level (i.e. pages) components and several reusable components within.

Srchr is a great example, but it has no concept of things like authorization or nested widgets which are prevalent in real-world line of business applications.

Application is the root, and functionality is loaded dynamically via routing or history. The Engine of Application State is the issue at hand not just control state. When I have my "App" at the root just refreshing the browser is going to cause all state to reload (which it should). Which components are loaded as well as what state those components are in starts to become a very complex issue. Using Srchr as a sample, some state gets pushed into localstorage (history) and we are mixing local state with remote state (the stuff we search for).

For mobile we have a need potentially for offline use, the App (say wrapped in Cordova) is there and items are cached locally until there is a connection then pushed up to the server; this means we need both a local Model and a remote one for the Component unless we start hacking at the current Model structure to override what create/update does.

These are the difficult things I would really like to see get addressed in a more standard way for CanJS and I think Component can solve a lot of this if it has the concept of how to do it even if its a plugin.

steeleprice commented May 23, 2013

Thank you very much for this great explanation. This is indeed exactly what I am trying to resolve in a better way right now with a single caveat, the large scale Application. It's Applications with High Level (i.e. pages) components and several reusable components within.

Srchr is a great example, but it has no concept of things like authorization or nested widgets which are prevalent in real-world line of business applications.

Application is the root, and functionality is loaded dynamically via routing or history. The Engine of Application State is the issue at hand not just control state. When I have my "App" at the root just refreshing the browser is going to cause all state to reload (which it should). Which components are loaded as well as what state those components are in starts to become a very complex issue. Using Srchr as a sample, some state gets pushed into localstorage (history) and we are mixing local state with remote state (the stuff we search for).

For mobile we have a need potentially for offline use, the App (say wrapped in Cordova) is there and items are cached locally until there is a connection then pushed up to the server; this means we need both a local Model and a remote one for the Component unless we start hacking at the current Model structure to override what create/update does.

These are the difficult things I would really like to see get addressed in a more standard way for CanJS and I think Component can solve a lot of this if it has the concept of how to do it even if its a plugin.

@steeleprice

This comment has been minimized.

Show comment
Hide comment
@steeleprice

steeleprice May 23, 2013

Maybe in addition to can.Component we need can.Mediate that is an Observe used specifically for communicating between Components and can.Facade which handles swapping out Model storage for local vs remote usage patterns similar to how Fixture is used for testing.

steeleprice commented May 23, 2013

Maybe in addition to can.Component we need can.Mediate that is an Observe used specifically for communicating between Components and can.Facade which handles swapping out Model storage for local vs remote usage patterns similar to how Fixture is used for testing.

@justinbmeyer

This comment has been minimized.

Show comment
Hide comment
@justinbmeyer

justinbmeyer May 23, 2013

Contributor

So, I was kinda thinking that your comments were more about high-level application architecture instead of can.component. Can you please sum them up in a forum post and remove some of the comments here to keep it can.component focused?

Contributor

justinbmeyer commented May 23, 2013

So, I was kinda thinking that your comments were more about high-level application architecture instead of can.component. Can you please sum them up in a forum post and remove some of the comments here to keep it can.component focused?

@justinbmeyer

This comment has been minimized.

Show comment
Hide comment
@justinbmeyer

justinbmeyer May 23, 2013

Contributor

@matthewp to better separate the model code from event code. I think it might make things easier to read.

Contributor

justinbmeyer commented May 23, 2013

@matthewp to better separate the model code from event code. I think it might make things easier to read.

@hyusetiawan

This comment has been minimized.

Show comment
Hide comment
@hyusetiawan

hyusetiawan Sep 17, 2013

are there any updates on this effort? Or has the discussion moved somewhere else?
Would love to know the progress on this and chip in a cent or two

hyusetiawan commented Sep 17, 2013

are there any updates on this effort? Or has the discussion moved somewhere else?
Would love to know the progress on this and chip in a cent or two

@daffl

This comment has been minimized.

Show comment
Hide comment
@daffl

daffl Sep 17, 2013

Contributor

There is a forum discussion and you can try the implementation out in the canComponent branch.

Contributor

daffl commented Sep 17, 2013

There is a forum discussion and you can try the implementation out in the canComponent branch.

@daffl

This comment has been minimized.

Show comment
Hide comment
@daffl

daffl Oct 11, 2013

Contributor

Closing this as it has been merged into master yesterday. Release pending for next week.

Contributor

daffl commented Oct 11, 2013

Closing this as it has been merged into master yesterday. Release pending for next week.

@daffl daffl closed this Oct 11, 2013

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment