produce in the element that is invoked within an each function

This snippet is a key part of my component's template:

{{#each displayResults}}
  <li {{action addSelection this}} {{bindAttr class=\":result active\"}}>
  {{#if controller.template}}
    {{yield}}
  {{else}}
    <span class=\"result-name\">{{displayHelper controller.searchPath}}</span>
  {{/if}}
  <\/li>
{{/each}}

I am looking to give users the ability to personalize the HTML used for displaying results.

The issue arises when {{yield}} is called within an {{#each}} helper. For example, if the component is instantiated like this:

{{#auto-suggest source=controller.employees destination=controller.chosenEmployees}}
<span class=\"result-name\"><img src="img/small_avatar.png"/>{{fullName}}</span>
{{/auto-suggest}}

Then the content inside the {{#auto-suggest}} block does not have access to the context of the {{#each}} helper in the component.

Is there a workaround for this limitation, or is it simply the nature of the component?

Answer №1

UPDATE

With the release of ember 1.10, a new syntax known as block params was introduced. This eliminates the need to override the _yield method. For example, within your component's template:

<ul>
  {{#each item in source}}
    <li>
    {{! Using the component block form for yielding}}
    {{#if template.blockParams}}
      {{yield item}}
    {{else}}
      {{item}}
    {{/if}}
    </li>
  {{/each}}
</ul>

You can now pass parameters to {{yield}} using as |var|:

{{auto-suggest source=model as |item|}}

{{#auto-suggest source=model as |item|}}
  <h1>{{item}}</h1>
{{/auto-suggest}}

Here is a simple live example

You have the flexibility to yield any variables by using

{{yield name age occupation hobbies}}
and capturing them in the component like so:

{{#x-foo user=model as |name age occupation hobbies|}}
  Hi my name is {{name}}, I am {{age}} years old. Major of the times I am {{occupation}}, but also love to {{hobbies}}.
{{/x-foo}}

FOR OLD VERSIONS

If you are working with older versions, you can override the default _yield method of Ember.Component. Simply change

context: get(parentView, 'context')
to context: get(view, 'context').

App.AutoSuggestComponent = Ember.Component.extend({
  _yield: function(context, options) {      
    var get = Ember.get, 
    view = options.data.view,
    parentView = this._parentView,
    template = get(this, 'template');

    if (template) {
      Ember.assert("A Component must have a parent view in order to yield.", parentView);      
      view.appendChild(Ember.View, {
        isVirtual: true,
        tagName: '',
        _contextView: parentView,
        template: template,
        context: get(view, 'context'), // Change here from 'parentView' to 'view'
        controller: get(parentView, 'controller'),
        templateData: { keywords: parentView.cloneKeywords() }
      });
    }
  }
});

Answer №2

Following Marcio Junior's advice, you have the option to enhance _yield without having to completely recreate the function. Instead of changing the behavior of _yield seamlessly, it is suggested to add an option to your component. For example:

 {{#whatever-component useComponentContext=true}}

In your component's JavaScript file, you can do the following:

 // Modifying _yield to utilize the current view
_yield: function(content, options) {
    var oldParentView = this._parentView;

    if (this.get('useComponentContext')) {
        // Temporarily set _parentView to the desired view
        this.set('_parentView', options.data.view);

        // Making the original context accessible through `_parent`
        options.data.view.get('context').set('_parent', oldParentView.get('context'));
    }

    // Call the default _yield method as usual
    var result = this._super.apply(this, arguments);

    // Restore _parentView
    this.set('_parentView', oldParentView);

    return result;
}

By implementing this approach, something like

{{!-- whatever-component.hbs --}}
{{#each something in somethings}}
  <div {{bind-attr title=something.id}}>
    {{#with something}}
      {{yield}}
    {{/with}}
  </div>
{{/each}}

{{!-- some-view.hbs --}}
{{#whatever-component.hbs}}
  <h1>{{id}}</h1>
  <p>{{someField}}</p>
  <div>{{_parent.theContextTheComponentIsBeingRenderedIn}}</div>
{{/whatever-component.hbs}}

will function as intended.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Sending the selected object from a dropdown in React back to its parent component

I have encountered a few issues with my React dropdown component. My main goal is to pass the selected object from the dropdown back to the Parent component. Currently, the dropdown list is functional and I am able to pass {this.state.selectedUser} back to ...

Can we incorporate various CSS libraries for individual components on our React site?

Let's say, I want to use different CSS libraries for each of my components - Home, About, Contact. Would it be feasible to utilize material ui for Home, semantic ui for About, and bootstrap for Contact? If so, what is the process for incorporating t ...

What is the best way to limit input to only numbers and special characters?

Here is the code snippet I am working with: <input style="text-align: right;font-size: 12px;" class='input' (keyup.enter)="sumTotal($event)" type="text" [ngModel]="field.value" (focusin)="focusin()" (focusout)="format()" (keyup.ente ...

How to surround values and keys with double quotes using regular expressions in JavaScript

I am in need of a valid JSON format to request ES. I currently have a string that looks like this: { time: { from:now-60d, mode:quick, to:now } } However, when I attempt to use JSON.parse, I encounter an error because my ...

Having trouble setting up Node.js on a Mac computer

Upon completing the regular installation on Mac, I am unable to find Node in the terminal. Even after defining the PATH with the line: export PATH=/usr/local/bin: $PATH, it still does not locate Node or npm in the terminal. ...

Scrolling to zoom in on the div content

I need the ability to resize the content within a div without changing the size of the div itself when the user scrolls. The function I currently have is as follows: var zoomable = document.getElementById('zoomable'), zX = 1; window.addEvent ...

Differences between Javascript object constructor and object literal

Similar Questions: Creating Objects - New Object or Object Literal Notation? Literal Notation VS. Constructor to Create Objects in JavaScript As I embark on my initial Javascript tutorial journey, I have come across two distinct methods of creatin ...

Implementing the useEffect hook in React to iterate over JSON data and update the state

Having trouble implementing job location filtering ("remote"/"in-person"/"hybrid") for my personal project. As a beginner in programming, I've spent quite some time troubleshooting the fetchLocationData function and passing URLSearchParams. I anticipa ...

What is causing the issue with $(document).append() method in jQuery version 1.9.1?

Why is the following code not functioning properly in jQuery 1.9.1? It worked fine in previous versions. $(function () { $(document).append(test); document.write('done'); }); var test = { version: "1.0", }; JSFiddle: http://jsfiddl ...

Unit testing an API built with Express and Mongoose using Jest

I have decided to implement a TDD approach for a user API that I am working on. Specifically, I am looking to add unit tests for two functions: userRegister and userLogin. Here is the code snippet from my app.js: 'use strict' const express = r ...

What is the best way to center text on an HTML canvas?

Is it possible to center an h1 tag in the middle of an HTML canvas using either JavaScript or HTML? I already have a CSS file for canvas styles. HTML <body> <canvas id="myCanvas"></canvas> <script src="canvas.js"></scri ...

How can you generate a "Package Contains Lower Node Version" error message during the installation of an NPM package if the node version is higher than the current system's node version?

I am looking for a way to trigger an error during the installation of an NPM package if the node version supported by that module does not match the system/server node version. Specifically, I want to prevent the installation of any npm module that suppor ...

Unraveling functions from a JavaScript promise in a web application using ExpressJS and NeDB

I have successfully implemented code that retrieves all users from my neDB-promisses: const fetchAllUsers = (res) => { db.find({}) .sort({ name: 1 }) .exec() .then( (content) => { res.status(2 ...

Proper Structure for Node System (BASIC)

Overview Recently, I entered the world of Node.js and built some basic back end functionality. However, I realized that everything was clustered in one file (index.js) which led me to explore tutorials on using express router middleware and adapting a mod ...

Issue with JQuery mobile: dynamically inserted popup fails to appear

Can you help me troubleshoot an issue with my function? It's supposed to take a text string and output the text surrounded by '¬¬¬' in a button with a pop-up menu attached. The button looks fine, but when clicked, the popup ul list doesn& ...

The significance of using the Spread operator in React-Redux Reducers

Exploring the essence of the spread operator has been quite intriguing. Based on my interpretation of the documentation, it seems that the spread syntax essentially duplicates the existing object and then gets replaced by a new object when one is introduce ...

Achieving a similar functionality to Spring Security ACL in a Node.js AWS Lambda serverless environment

I am tackling a javascript challenge that has me stumped. Specifically, I am trying to figure out how to implement fine-grained authorization using an AWS serverless approach. In Spring security ACL, users can be banned from specific tasks at the instanc ...

Filtering MUI Data Grid by array elements

I am in the process of developing a management system that utilizes three MUIDataGrids. Although only one grid is displayed at a time, users can switch between the three grids by clicking on tabs located above. The setup I have resembles the Facebook Ads ...

Encountering a Javascript error while trying to optimize bundling operations

After bundling my JavaScript with the .net setting BundleTable.EnableOptimizations = true;, I've encountered a peculiar issue. Here's the snippet of the generated code causing the error (simplified): var somVar = new b({ searchUrl: "/so ...

How to perfect the alignment of TimePicker in angular UI

I'm dealing with the code below: <ul class="dropdown-menu custom-scroll dropdown-label custom-width" role="menu" aria-labelledby="btn-append-to-body" ng-show="!display" > <li role ...