From bcef7938a9b3c6e0bd05a3affa2fa227242d719a Mon Sep 17 00:00:00 2001 From: Matthew Beale Date: Mon, 10 Aug 2015 15:47:15 -0400 Subject: [PATCH] [DOC release] Bring back docs for several helpers (cherry picked from commit 99aaa34224e96df97b95a2ceeba9755af356fc0a) --- .../ember-htmlbars/lib/keywords/collection.js | 126 +++++++++++- .../ember-htmlbars/lib/keywords/partial.js | 43 +++- .../ember-htmlbars/lib/keywords/readonly.js | 5 + .../ember-htmlbars/lib/keywords/textarea.js | 188 +++++++++++++++++- packages/ember-htmlbars/lib/keywords/view.js | 180 ++++++++++++++++- packages/ember-htmlbars/lib/keywords/with.js | 5 + 6 files changed, 543 insertions(+), 4 deletions(-) diff --git a/packages/ember-htmlbars/lib/keywords/collection.js b/packages/ember-htmlbars/lib/keywords/collection.js index f8ec2980099..92bd45d404d 100644 --- a/packages/ember-htmlbars/lib/keywords/collection.js +++ b/packages/ember-htmlbars/lib/keywords/collection.js @@ -1,6 +1,6 @@ /** @module ember -@submodule ember-htmlbars +@submodule ember-templates */ import { readViewFactory } from 'ember-views/streams/utils'; @@ -8,6 +8,130 @@ import CollectionView from 'ember-views/views/collection_view'; import ViewNodeManager from 'ember-htmlbars/node-managers/view-node-manager'; import { assign } from 'ember-metal/merge'; +/** + `{{collection}}` is a template helper for adding instances of + `Ember.CollectionView` to a template. See [Ember.CollectionView](/api/classes/Ember.CollectionView.html) + for additional information on how a `CollectionView` functions. + + `{{collection}}`'s primary use is as a block helper with a `contentBinding` + option pointing towards an `Ember.Array`-compatible object. An `Ember.View` + instance will be created for each item in its `content` property. Each view + will have its own `content` property set to the appropriate item in the + collection. + + The provided block will be applied as the template for each item's view. + + Given an empty `` the following template: + + ```handlebars + {{! application.hbs }} + {{#collection content=model}} + Hi {{view.content.name}} + {{/collection}} + ``` + + And the following application code + + ```javascript + App = Ember.Application.create(); + App.ApplicationRoute = Ember.Route.extend({ + model: function() { + return [{name: 'Yehuda'},{name: 'Tom'},{name: 'Peter'}]; + } + }); + ``` + + The following HTML will result: + + ```html +
+
Hi Yehuda
+
Hi Tom
+
Hi Peter
+
+ ``` + + ### Non-block version of collection + + If you provide an `itemViewClass` option that has its own `template` you may + omit the block. + + The following template: + + ```handlebars + {{! application.hbs }} + {{collection content=model itemViewClass="an-item"}} + ``` + + And application code + + ```javascript + App = Ember.Application.create(); + App.ApplicationRoute = Ember.Route.extend({ + model: function() { + return [{name: 'Yehuda'},{name: 'Tom'},{name: 'Peter'}]; + } + }); + + App.AnItemView = Ember.View.extend({ + template: Ember.Handlebars.compile("Greetings {{view.content.name}}") + }); + ``` + + Will result in the HTML structure below + + ```html +
+
Greetings Yehuda
+
Greetings Tom
+
Greetings Peter
+
+ ``` + + ### Specifying a CollectionView subclass + + By default the `{{collection}}` helper will create an instance of + `Ember.CollectionView`. You can supply a `Ember.CollectionView` subclass to + the helper by passing it as the first argument: + + ```handlebars + {{#collection "my-custom-collection" content=model}} + Hi {{view.content.name}} + {{/collection}} + ``` + + This example would look for the class `App.MyCustomCollection`. + + ### Forwarded `item.*`-named Options + + As with the `{{view}}`, helper options passed to the `{{collection}}` will be + set on the resulting `Ember.CollectionView` as properties. Additionally, + options prefixed with `item` will be applied to the views rendered for each + item (note the camelcasing): + + ```handlebars + {{#collection content=model + itemTagName="p" + itemClassNames="greeting"}} + Howdy {{view.content.name}} + {{/collection}} + ``` + + Will result in the following HTML structure: + + ```html +
+

Howdy Yehuda

+

Howdy Tom

+

Howdy Peter

+
+ ``` + + @method collection + @for Ember.Templates.helpers + @deprecated Use `{{each}}` helper instead. + @public +*/ export default { setupState(state, env, scope, params, hash) { var read = env.hooks.getValue; diff --git a/packages/ember-htmlbars/lib/keywords/partial.js b/packages/ember-htmlbars/lib/keywords/partial.js index b2735d06bc9..d776ca68b1e 100644 --- a/packages/ember-htmlbars/lib/keywords/partial.js +++ b/packages/ember-htmlbars/lib/keywords/partial.js @@ -1,11 +1,52 @@ /** @module ember -@submodule ember-htmlbars +@submodule ember-templates */ import lookupPartial from 'ember-views/system/lookup_partial'; import { internal } from 'htmlbars-runtime'; +/** + The `partial` helper renders another template without + changing the template context: + + ```handlebars + {{foo}} + {{partial "nav"}} + ``` + + The above example template will render a template named + "_nav", which has the same context as the parent template + it's rendered into, so if the "_nav" template also referenced + `{{foo}}`, it would print the same thing as the `{{foo}}` + in the above example. + + If a "_nav" template isn't found, the `partial` helper will + fall back to a template named "nav". + + ### Bound template names + + The parameter supplied to `partial` can also be a path + to a property containing a template name, e.g.: + + ```handlebars + {{partial someTemplateName}} + ``` + + The above example will look up the value of `someTemplateName` + on the template context (e.g. a controller) and use that + value as the name of the template to render. If the resolved + value is falsy, nothing will be rendered. If `someTemplateName` + changes, the partial will be re-rendered using the new template + name. + + + @method partial + @for Ember.Templates.helpers + @param {String} partialName the name of the template to render minus the leading underscore + @public +*/ + export default { setupState(state, env, scope, params, hash) { return { partialName: env.hooks.getValue(params[0]) }; diff --git a/packages/ember-htmlbars/lib/keywords/readonly.js b/packages/ember-htmlbars/lib/keywords/readonly.js index c0b8e9165e5..dd954d1114f 100644 --- a/packages/ember-htmlbars/lib/keywords/readonly.js +++ b/packages/ember-htmlbars/lib/keywords/readonly.js @@ -1,3 +1,8 @@ +/** +@module ember +@submodule ember-templates +*/ + import { MUTABLE_REFERENCE } from 'ember-htmlbars/keywords/mut'; export default function readonly(morph, env, scope, originalParams, hash, template, inverse) { diff --git a/packages/ember-htmlbars/lib/keywords/textarea.js b/packages/ember-htmlbars/lib/keywords/textarea.js index daf57bcc087..3687dedbc4c 100644 --- a/packages/ember-htmlbars/lib/keywords/textarea.js +++ b/packages/ember-htmlbars/lib/keywords/textarea.js @@ -1,8 +1,194 @@ /** @module ember -@submodule ember-htmlbars +@submodule ember-templates */ +/** + `{{textarea}}` inserts a new instance of ` + ``` + + Bound: + + In the following example, the `writtenWords` property on `App.ApplicationController` + will be updated live as the user types 'Lots of text that IS bound' into + the text area of their browser's window. + + ```javascript + App.ApplicationController = Ember.Controller.extend({ + writtenWords: "Lots of text that IS bound" + }); + ``` + + ```handlebars + {{textarea value=writtenWords}} + ``` + + Would result in the following HTML: + + ```html + + ``` + + If you wanted a one way binding between the text area and a div tag + somewhere else on your screen, you could use `Ember.computed.oneWay`: + + ```javascript + App.ApplicationController = Ember.Controller.extend({ + writtenWords: "Lots of text that IS bound", + outputWrittenWords: Ember.computed.oneWay("writtenWords") + }); + ``` + + ```handlebars + {{textarea value=writtenWords}} + +
+ {{outputWrittenWords}} +
+ ``` + + Would result in the following HTML: + + ```html + + + <-- the following div will be updated in real time as you type --> + +
+ Lots of text that IS bound +
+ ``` + + Finally, this example really shows the power and ease of Ember when two + properties are bound to eachother via `Ember.computed.alias`. Type into + either text area box and they'll both stay in sync. Note that + `Ember.computed.alias` costs more in terms of performance, so only use it when + your really binding in both directions: + + ```javascript + App.ApplicationController = Ember.Controller.extend({ + writtenWords: "Lots of text that IS bound", + twoWayWrittenWords: Ember.computed.alias("writtenWords") + }); + ``` + + ```handlebars + {{textarea value=writtenWords}} + {{textarea value=twoWayWrittenWords}} + ``` + + ```html + + + <-- both updated in real time --> + + + ``` + + ### Actions + + The helper can send multiple actions based on user events. + + The action property defines the action which is send when + the user presses the return key. + + ```handlebars + {{input action="submit"}} + ``` + + The helper allows some user events to send actions. + +* `enter` +* `insert-newline` +* `escape-press` +* `focus-in` +* `focus-out` +* `key-press` + + For example, if you desire an action to be sent when the input is blurred, + you only need to setup the action name to the event name property. + + ```handlebars + {{textarea focus-in="alertMessage"}} + ``` + + See more about [Text Support Actions](/api/classes/Ember.TextArea.html) + + ### Extension + + Internally, `{{textarea}}` creates an instance of `Ember.TextArea`, passing + arguments from the helper to `Ember.TextArea`'s `create` method. You can + extend the capabilities of text areas in your application by reopening this + class. For example, if you are building a Bootstrap project where `data-*` + attributes are used, you can globally add support for a `data-*` attribute + on all `{{textarea}}`s' in your app by reopening `Ember.TextArea` or + `Ember.TextSupport` and adding it to the `attributeBindings` concatenated + property: + + ```javascript + Ember.TextArea.reopen({ + attributeBindings: ['data-error'] + }); + ``` + + Keep in mind when writing `Ember.TextArea` subclasses that `Ember.TextArea` + itself extends `Ember.Component`. Expect isolated component semantics, not + legacy 1.x view semantics (like `controller` being present). + + See more about [Ember components](/api/classes/Ember.Component.html) + + @method textarea + @for Ember.Templates.helpers + @param {Hash} options + @public +*/ export default function textarea(morph, env, scope, originalParams, hash, template, inverse, visitor) { env.hooks.component(morph, env, scope, '-text-area', originalParams, hash, { default: template, inverse }, visitor); return true; diff --git a/packages/ember-htmlbars/lib/keywords/view.js b/packages/ember-htmlbars/lib/keywords/view.js index a6298c436c3..efda98204cf 100644 --- a/packages/ember-htmlbars/lib/keywords/view.js +++ b/packages/ember-htmlbars/lib/keywords/view.js @@ -1,12 +1,190 @@ /** @module ember -@submodule ember-htmlbars +@submodule ember-templates */ import { readViewFactory } from 'ember-views/streams/utils'; import EmberView from 'ember-views/views/view'; import ViewNodeManager from 'ember-htmlbars/node-managers/view-node-manager'; +/** + `{{view}}` inserts a new instance of an `Ember.View` into a template passing its + options to the `Ember.View`'s `create` method and using the supplied block as + the view's own template. + + An empty `` and the following template: + + ```handlebars + A span: + {{#view tagName="span"}} + hello. + {{/view}} + ``` + + Will result in HTML structure: + + ```html + + + +
+ A span: + + Hello. + +
+ + ``` + + ### `parentView` setting + + The `parentView` property of the new `Ember.View` instance created through + `{{view}}` will be set to the `Ember.View` instance of the template where + `{{view}}` was called. + + ```javascript + aView = Ember.View.create({ + template: Ember.Handlebars.compile("{{#view}} my parent: {{parentView.elementId}} {{/view}}") + }); + + aView.appendTo('body'); + ``` + + Will result in HTML structure: + + ```html +
+
+ my parent: ember1 +
+
+ ``` + + ### Setting CSS id and class attributes + + The HTML `id` attribute can be set on the `{{view}}`'s resulting element with + the `id` option. This option will _not_ be passed to `Ember.View.create`. + + ```handlebars + {{#view tagName="span" id="a-custom-id"}} + hello. + {{/view}} + ``` + + Results in the following HTML structure: + + ```html +
+ + hello. + +
+ ``` + + The HTML `class` attribute can be set on the `{{view}}`'s resulting element + with the `class` or `classNameBindings` options. The `class` option will + directly set the CSS `class` attribute and will not be passed to + `Ember.View.create`. `classNameBindings` will be passed to `create` and use + `Ember.View`'s class name binding functionality: + + ```handlebars + {{#view tagName="span" class="a-custom-class"}} + hello. + {{/view}} + ``` + + Results in the following HTML structure: + + ```html +
+ + hello. + +
+ ``` + + ### Supplying a different view class + + `{{view}}` can take an optional first argument before its supplied options to + specify a path to a custom view class. + + ```handlebars + {{#view "custom"}}{{! will look up App.CustomView }} + hello. + {{/view}} + ``` + + The first argument can also be a relative path accessible from the current + context. + + ```javascript + MyApp = Ember.Application.create({}); + MyApp.OuterView = Ember.View.extend({ + innerViewClass: Ember.View.extend({ + classNames: ['a-custom-view-class-as-property'] + }), + template: Ember.Handlebars.compile('{{#view view.innerViewClass}} hi {{/view}}') + }); + + MyApp.OuterView.create().appendTo('body'); + ``` + + Will result in the following HTML: + + ```html +
+
+ hi +
+
+ ``` + + ### Blockless use + + If you supply a custom `Ember.View` subclass that specifies its own template + or provide a `templateName` option to `{{view}}` it can be used without + supplying a block. Attempts to use both a `templateName` option and supply a + block will throw an error. + + ```javascript + var App = Ember.Application.create(); + App.WithTemplateDefinedView = Ember.View.extend({ + templateName: 'defined-template' + }); + ``` + + ```handlebars + {{! application.hbs }} + {{view 'with-template-defined'}} + ``` + + ```handlebars + {{! defined-template.hbs }} + Some content for the defined template view. + ``` + + ### `viewName` property + + You can supply a `viewName` option to `{{view}}`. The `Ember.View` instance + will be referenced as a property of its parent view by this name. + + ```javascript + aView = Ember.View.create({ + template: Ember.Handlebars.compile('{{#view viewName="aChildByName"}} hi {{/view}}') + }); + + aView.appendTo('body'); + aView.get('aChildByName') // the instance of Ember.View created by {{view}} helper + ``` + + @method view + @for Ember.Templates.helpers + @public + @deprecated +*/ + export default { setupState(state, env, scope, params, hash) { var read = env.hooks.getValue; diff --git a/packages/ember-htmlbars/lib/keywords/with.js b/packages/ember-htmlbars/lib/keywords/with.js index 2975cdaa850..5e0ca5dfc98 100644 --- a/packages/ember-htmlbars/lib/keywords/with.js +++ b/packages/ember-htmlbars/lib/keywords/with.js @@ -1,3 +1,8 @@ +/** +@module ember +@submodule ember-templates +*/ + import Ember from 'ember-metal/core'; import { internal } from 'htmlbars-runtime';