5.8 components-composing Components (combination)

Source: Internet
Author: User

I. Overview

When you combine it with another component, the component really does all of its potential. For example, the <ul> element, only the <li> element is suitable as its child element. If we want the same type of behavior, then we have to assemble the components.

Just as we combine HTML elements, we can use them in the same way as components.

App/templates/application.hbs

{{#user-list users=activeusers sortby= ' name ' as |user|}  } {{User-card User=user}} {{/user-list}}

Second, Component Blocks

A component can be used in two forms, just like a normal HTML element.

1. Inline Form

App/templates/application.hbs

{{User-list users=activeusers}}

This is the basic non-block-level component, which does not provide the ability for users to insert their own content into a given component.

2. Block Form

App/templates/application.hbs

{{#user-list users=activeusers}}  {{!--custom template here--}} {{/user-list}}

(1) In order to assemble components, we must use block form, but we must also be able to use the form of our component. This can be done by using the Hasblock property in the component.

App/templates/components/user-list.hbs

{{#if hasblock}}  {yield}} {{Else}}   < P > No Block Specified</p>{{/if}}

Once we know that the component is using block format, we can populate any content that the user placed in the block with the {{yield}} helper where we want it to unfold.

(2) The {yield} helper can be used multiple times in the template of a component, allowing us to create a component that works like a list, where we output a title and produce content for each post.

App/templates/components/post-list.hbs

{{#each posts as |post|}}   < H3 > {{Post.title}} </ H3 >  < P > {yield}} </ P > {{/each}}

Can be used like this:

App/templates/posts.hbs

{{#post-list posts=headlineposts}}  Greatest Post ever! {{/post-list}}

Generated HTML:

<DivID= "ember123"class= "Ember-view">  <H3>Tomster goes to Town</H3>  <P>Greatest Post ever!</P>  <H3>Tomster on vacation</H3>  <P>Greatest Post ever!</P></Div>

But does it just use it to output the same thing over and over again? Don't we want to customize our posts and show the right content? Of course we want to. Let's explore the {{yield}} helper a little bit.

Third, Data down

1. In order to complete the composite template, we need to pass the data to these templates. Can be implemented using the {{yield}} helper described above.

2. As we saw in the previous section, the content defined in the component's block will be produced into the layout of the component, and{yield}} is defined in this place. In addition, the{yield} helper also allows us to send data through the production parameters back to the scope of the component we call.

{yield}} {yield "post"}} {Yield Item}} {{Yield this ' footer '}}

3. The default yield does not send any data, but you can provide any number of parameters. In addition, the resulting values are ordered in order, so you can get them in the same order because the components expose them. Sending data allows the user of the component to use this data. For the user to get the data, he needs to know what data the component exposes, which is why the document is so important, and the data generated from there can be accessed using the operator. Let's look at an example:

App/components/user-list/template.hbs

{{#each users as |user|}}  {Yield User}} {{/each}}

This {{user-list}} component will be generated multiple times as its user. We can use the following method to eliminate it.

App/users/template.hbs

{{#user-list users=users as |user|}}  {{User-card User=user}} {{/user-list}}

Now {{User-card}} gets to the current user because {{yield user}} is within {{each}} block, when {{user-list}} A change occurs while traversing each user. Although this is good, what happens if we use our component that does not contain a block, such as {{user-list users=users}} ? This makes the component nearly useless because nothing is produced, but the users are still traversed.

4. Let's Mix the Hasblock property and see if we can make it more useful.

App/components/user-list/template.hbs

{{#if Hasblock}} {{#each users as |user|}}  {Yield User}} {{/each}}  {{Else}}    {{#each users as |user|}} < Sectionclass= "User-info">      <H3>{{User.Name}}</H3>      <P>{{User.bio}}</P>    </ Section>{{/each}}{{/if}}

This makes our component more useful because it has a normal default value, but it also allows us to override these default values. By using {{yield}} we can pass our parameters to the user. This makes the concept of passing data very useful.

Iv.{{compoonent}} Help

1. In order to understand the {{ component}} helper, we will add the following new functionality for { {user-list} }:

    • For each type of usage, we want to use a different layout.
    • This list can also be toggled between basic and verbose modes.

2. Add a new type of user, a superuser, who will behave differently in our reference program. How do you use the new data to show different UI for different types? This is what the {{component}} helper will show. This helper allows us to select a component at run time.

3. Because we have two types of users, ' public ' and ' Superuser ', and we want to render one component for each type plus a simple and detailed two modes. We have the following component names:

    • basic-card-public
    • basic-card-superuser
    • detailed-card-public
    • detailed-card-superuser

We can create these names by using the nested form of the {{contact}} Helper:

{{component (Concat ' basic-card-' User.type)}}

Now our component names are valid, because using dashes, we can put two patterns together to form a complete template.

App/users/template.hbs

 {{#user-list users=users as |user basicmode|}}    {{#if Basicmode}}  {{component (Concat ' basic-card-' User.type) User=user}}    {{Else}}  {{component (Concat ' detailed-card-' User.type) User=user}} {{/if}} {{/user-list}}  
    • Now we have {{basic-card-superuser}} and {{detailed-card-public}} is loaded to the appropriate location.
    • using nested in form The ' concat ' helper allows us to implement this.
    • nested helpers evaluated in front of the parent helper , the helper can then use the nested .
    • if helper.

4. In addition to using {{component}}, we also have a second generated value for the functionality of the basic/detailed mode, which we have added to yield, such as {{yield user basic}}.

5. The user can decide how to name the resulting value. We can name it like this:

App/users/template.hbs

{{#user-list users=users as |usermodel isbasic|}  } {{! Something creative here}} {{/user-list}}

V. Actions up

1. Now that we know how to send data, we may want to manipulate the data through some user interaction, such as changing the user's avatar. We can do this through the actions.

2. We will look for a {{user-profile}} component to implement a save action. By generating an action as a parameter, the user is allowed to use the component without having to save it, but it can still trigger save.

App/components/user-profile/component.js

Import Ember from ' Ember 'default  Ember.Component.extend ({  actions: {    saveuser ()} {       varthis. Get (' user ');      User.save ()        = {          thistrue);        })        . Catch (Error = {          this. Set (' Saveerror ', error);        });}}  ); 

App/components/user-profile/template.hbs

{{! Most likely we had some markup here}} {{Yield profile (action ' Saveuser ')}}

3. So now the user will get our defined data and action. Let's see if the component is consumed as a block.

App/templates/user/profile.hbs

{{#user-profile user=user as |profile saveuser|}  } {{User-avatar url=profile.imageurl Onchange=saveuser}} {{/user-profile}}

As can be seen from this example, the user can hook into the {{user-profile}} component's saveuser action, which is embedded in the helper (action "Saveuser") delivery. This helper reads a property in an actions hash that is not in the current context, and then creates a closure and passes the parameters through the function.

4. We can also use this format to place an action on native HTML elements (such as input buttons):

{{#user-profile user=user as |profile saveuser|}   } <  type= "button"  onclickSaveuser}}>Save< /button>{{/user-profile}}

This is very useful because we reuse these elements to provide the EVETN hooks. This makes the components more reusable because we can combine smaller components to do one thing better.

Six, wrapping up

The composition component is about the partitioning function as a reusable block, which makes it easier to exit and combine it more easily to work well with them. This can also be easily tested because we try to do everything in a monolithic component, and I can split the function into smaller parts.

5.8 components-composing Components (combination)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.