コンポーネントの動的生成によるui:messageのラッパー

ドキュメントに、`$A.componentService.newComponentAsync`を使って`ui:message`を動的に作るサンプルが記載されていました。
しかし、そのまま書いたら恒例の内部エラーが出力されてしまいました。

コンポーネントの入れ子生成ができないようです。
下記のようにタイトルだけ出力させるようにしたら動作しました。

```xml:SimpleSample.app
<aura:application>
    <tiwasakidemo:TitleOnlyMessage />
</aura:application>
```

```xml:TitleOnlyMessage.cmp
<aura:component>   
    <aura:handler name="init" value="{!this}" action="{!c.doInit}" />

    <div aura:id="placeholder">value to be replaced.</div>
</aura:component>
```

```js:TitleOnlyMessage.js
({
	doInit : function(component, event, helper) {
        var def = {
            componentDef: 'markup://ui:message',
            attributes : {
                values : {
                    title : 'hello'
                }
            }
        };
        $A.componentService.newComponentAsync(
            this,
            function(message) {
                var placeholder = component.find('placeholder');
                placeholder.set('v.body', message);
            },
            def
        );
    }
})
```

しかし、同等の記述をタグで記述するとなぜか保存時にエラーになってしまいます。

```xml:.cmp
    <ui:message title="hello">v.body</ui:message>
    <ui:message title="hello"></ui:message>
```

`v.body`の`Component[]`型の取り扱いが鬼門のようです。
取り急ぎ、ドキュメントにあるサンプルと同じく文字列型で動作するようにしてみましょう。

コンポーネントの入れ子生成ができないならば、１つずつ作成すれば良いですね。
引数は[ui:messageのソース](https://github.com/forcedotcom/aura/blob/master/aura-components/src/main/components/ui/message/message.cmp#L19-L21)からいただいてきました。

```message.cmp
<aura:component>   
    <aura:attribute name="message" type="String" />
    <aura:attribute access="GLOBAL" name="title" type="String" description="The title text for the message."/>
    <aura:attribute access="GLOBAL" name="severity" type="String" default="message" description="The severity of the message. Possible values:  message (default), confirm, info, warning, error"/>
    <aura:attribute access="GLOBAL" name="closable" type="Boolean" default="false" description="Specifies whether to display an 'x' that will close the alert when clicked. Default value is 'false'."/>
    <aura:handler name="init" value="{!this}" action="{!c.doInit}" />

    <div aura:id="placeholder"></div>
</aura:component>
```

```js:messageController.js
({
    doInit : function(component, event, helper) {
        var title = component.get('v.title');
        var message = component.get('v.message');
        var severity = component.get('v.severity') || 'message';
        var closable = component.get('v.closable') || false;
        if ($A.util.isUndefinedOrNull(message) && $A.util.isUndefinedOrNull(title))
            message = severity;
        
        var defUiMessage = {
            componentDef : 'markup://ui:message',
            attributes : {
                values : {
                    title : title,
                    severity : severity,
                    closable  : closable
                }
            }
        };
        var defUiOutputText = {
            componentDef : 'markup://ui:outputText',
            attributes : {
                values : {
                    value : message
                }
            }
        };
        
        var that = this;
        $A.componentService.newComponentAsync(
            this,
            function(uiMessage) {
                $A.componentService.newComponentAsync(
                    that,
                    function(uiOutputText) {
                        if (!$A.util.isUndefinedOrNull(message))
	                        uiMessage.set('v.body', uiOutputText);
                        var placeholder = component.find('placeholder');
                        placeholder.set('v.body', uiMessage);
                    },
                    defUiOutputText
                );
            },
            defUiMessage
        );
    }
})
```

こんな風に書くと

```xml:sample.app
<aura:application>
    <tiwasakidemo:message severity="message" title="hello" message="world" closable="true" />
    <tiwasakidemo:message severity="confirm" title="hello" message="world" closable="true" />
    <tiwasakidemo:message severity="debug" title="hello" message="world" closable="true" />
    <tiwasakidemo:message severity="info" title="hello" message="world" closable="true" />
    <tiwasakidemo:message severity="warning" title="hello" message="world" closable="true" />
    <tiwasakidemo:message severity="error" title="hello" message="world" closable="true" />
</aura:application>
```

こうなります。

![スクリーンショット 2014-12-18 12.40.26.png](https://qiita-image-store.s3.amazonaws.com/0/44645/e322e30d-2106-ae92-5771-cecd10b2e0f9.png)

これらのスタイルは`uiMessage`クラス、`.uiMessgae.error`セレクターなどに対して設定されていますので、適宜cssにて上書きすることもできます。

それぞれのパラメーターは省略もできるようになっていますので指定を色々変えて試してみてください。
さらっと書きましたがJavaScript書き慣れていない方はカンマや括弧の位置、クロージャーなどの記述にご注意ください。