Exemplo n.º 1
0
export function componentHelper(params, hash, options, env) {
  Ember.assert(
    "The `component` helper expects exactly one argument, plus name/property values.",
    params.length === 1
  );

  var componentNameParam = params[0];
  var container = this.container || read(this._keywords.view).container;

  var props = {
    helperName: options.helperName || 'component'
  };
  if (options.template) {
    props.template = options.template;
  }

  var viewClass;
  if (isStream(componentNameParam)) {
    viewClass = BoundComponentView;
    props = { _boundComponentOptions: Ember.merge(hash, props) };
    props._boundComponentOptions.componentNameStream = componentNameParam;
  } else {
    viewClass = readComponentFactory(componentNameParam, container);
    if (!viewClass) {
      throw new EmberError('HTMLBars error: Could not find component named "' + componentNameParam + '".');
    }
    mergeViewBindings(this, props, hash);
  }

  appendTemplatedView(this, options.morph, viewClass, props);
}
Exemplo n.º 2
0
export function renderHelper(params, hash, options, env) {
  var currentView = env.data.view;
  var container, router, controller, view, initialContext;

  var name = params[0];
  var context = params[1];

  container = currentView._keywords.controller.value().container;
  router = container.lookup('router:main');

  Ember.assert(
    "The first argument of {{render}} must be quoted, e.g. {{render \"sidebar\"}}.",
    typeof name === 'string'
  );

  Ember.assert(
    "The second argument of {{render}} must be a path, e.g. {{render \"post\" post}}.",
    params.length < 2 || isStream(params[1])
  );


  if (params.length === 1) {
    // use the singleton controller
    Ember.assert(
      "You can only use the {{render}} helper once without a model object as " +
      "its second argument, as in {{render \"post\" post}}.",
      !router || !router._lookupActiveView(name)
    );
  } else if (params.length === 2) {
    // create a new controller
    initialContext = context.value();
  } else {
    throw new EmberError("You must pass a templateName to render");
  }

  // # legacy namespace
  name = name.replace(/\//g, '.');
  // \ legacy slash as namespace support


  view = container.lookup('view:' + name) || container.lookup('view:default');

  // provide controller override
  var controllerName;
  var controllerFullName;

  if (hash.controller) {
    controllerName = hash.controller;
    controllerFullName = 'controller:' + controllerName;
    delete hash.controller;

    Ember.assert(
      "The controller name you supplied '" + controllerName + "' " +
      "did not resolve to a controller.",
      container._registry.has(controllerFullName)
    );
  } else {
    controllerName = name;
    controllerFullName = 'controller:' + controllerName;
  }

  var parentController = currentView._keywords.controller.value();

  // choose name
  if (params.length > 1) {
    var factory = container.lookupFactory(controllerFullName) ||
                  generateControllerFactory(container, controllerName, initialContext);

    controller = factory.create({
      modelBinding: context, // TODO: Use a StreamBinding
      parentController: parentController,
      target: parentController
    });

    view.one('willDestroyElement', function() {
      controller.destroy();
    });
  } else {
    controller = container.lookup(controllerFullName) ||
                 generateController(container, controllerName);

    controller.setProperties({
      target: parentController,
      parentController: parentController
    });
  }

  hash.viewName = camelize(name);

  var templateName = 'template:' + name;
  Ember.assert(
    "You used `{{render '" + name + "'}}`, but '" + name + "' can not be " +
    "found as either a template or a view.",
    container._registry.has("view:" + name) || container._registry.has(templateName) || !!options.template
  );
  var template = options.template || container.lookup(templateName);

  if (router && !initialContext) {
    router._connectActiveView(name, view);
  }

  var props = {
    template: template,
    controller: controller,
    helperName: 'render "' + name + '"'
  };

  mergeViewBindings(currentView, props, hash);
  appendTemplatedView(currentView, options.morph, view, props);
}
Exemplo n.º 3
0
export function collectionHelper(params, hash, options, env) {
  var path = params[0];

  Ember.deprecate("Using the {{collection}} helper without specifying a class has been" +
                  " deprecated as the {{each}} helper now supports the same functionality.", path !== 'collection');

  Ember.assert("You cannot pass more than one argument to the collection helper", params.length <= 1);

  var data     = env.data;
  var template = options.template;
  var inverse  = options.inverse;
  var view     = data.view;

  // This should be deterministic, and should probably come from a
  // parent view and not the controller.
  var  controller = get(view, 'controller');
  var  container = (controller && controller.container ? controller.container : view.container);

  // If passed a path string, convert that into an object.
  // Otherwise, just default to the standard class.
  var collectionClass;
  if (path) {
    collectionClass = readViewFactory(path, container);
    Ember.assert(fmt("%@ #collection: Could not find collection class %@", [data.view, path]), !!collectionClass);
  } else {
    collectionClass = CollectionView;
  }

  var itemHash = {};
  var match;

  // Extract item view class if provided else default to the standard class
  var collectionPrototype = collectionClass.proto();
  var itemViewClass;

  if (hash.itemView) {
    itemViewClass = readViewFactory(hash.itemView, container);
  } else if (hash.itemViewClass) {
    itemViewClass = readViewFactory(hash.itemViewClass, container);
  } else {
    itemViewClass = collectionPrototype.itemViewClass;
  }

  if (typeof itemViewClass === 'string') {
    itemViewClass = container.lookupFactory('view:'+itemViewClass);
  }

  Ember.assert(fmt("%@ #collection: Could not find itemViewClass %@", [data.view, itemViewClass]), !!itemViewClass);

  delete hash.itemViewClass;
  delete hash.itemView;

  // Go through options passed to the {{collection}} helper and extract options
  // that configure item views instead of the collection itself.
  for (var prop in hash) {
    if (prop === 'itemController' || prop === 'itemClassBinding') {
      continue;
    }
    if (hash.hasOwnProperty(prop)) {
      match = prop.match(/^item(.)(.*)$/);
      if (match) {
        var childProp = match[1].toLowerCase() + match[2];

        if (IS_BINDING.test(prop)) {
          itemHash[childProp] = view._getBindingForStream(hash[prop]);
        } else {
          itemHash[childProp] = hash[prop];
        }
        delete hash[prop];
      }
    }
  }

  if (template) {
    itemHash.template = template;
    delete options.template;
  }

  var emptyViewClass;
  if (inverse) {
    emptyViewClass = get(collectionPrototype, 'emptyViewClass');
    emptyViewClass = emptyViewClass.extend({
          template: inverse,
          tagName: itemHash.tagName
    });
  } else if (hash.emptyViewClass) {
    emptyViewClass = readViewFactory(hash.emptyViewClass, container);
  }
  if (emptyViewClass) { hash.emptyView = emptyViewClass; }

  if (hash.keyword) {
    itemHash._contextBinding = Binding.oneWay('_parentView.context');
  } else {
    itemHash._contextBinding = Binding.oneWay('content');
  }

  var viewOptions = mergeViewBindings(this, {}, itemHash);

  if (hash.itemClassBinding) {
    var itemClassBindings = hash.itemClassBinding.split(' ');
    viewOptions.classNameBindings = map(itemClassBindings, function(classBinding) {
      return streamifyClassNameBinding(view, classBinding);
    });
  }

  hash.itemViewClass = itemViewClass;
  hash._itemViewProps = viewOptions;

  options.helperName = options.helperName || 'collection';

  return env.helpers.view.helperFunction.call(this, [collectionClass], hash, options, env);
}