{"id":24793,"date":"2024-02-12T12:05:51","date_gmt":"2024-02-12T11:05:51","guid":{"rendered":"https:\/\/www.angulararchitects.io\/?p=24793"},"modified":"2024-03-07T18:27:43","modified_gmt":"2024-03-07T17:27:43","slug":"component-communication-with-signals-inputs-two-way-bindings-and-content-view-queries","status":"publish","type":"post","link":"https:\/\/www.angulararchitects.io\/en\/blog\/component-communication-with-signals-inputs-two-way-bindings-and-content-view-queries\/","title":{"rendered":"Component Communication with Signals: Inputs, Two-Way Bindings, and Content\/ View Queries"},"content":{"rendered":"<div class=\"wp-post-series-box series-signals wp-post-series-box--expandable\">\n\t\t\t<input id=\"collapsible-series-signals69e4dcb695691\" class=\"wp-post-series-box__toggle_checkbox\" type=\"checkbox\">\n\t\n\t<label\n\t\tclass=\"wp-post-series-box__label\"\n\t\t\t\t\tfor=\"collapsible-series-signals69e4dcb695691\"\n\t\t\ttabindex=\"0\"\n\t\t\t\t>\n\t\t<p class=\"wp-post-series-box__name wp-post-series-name\">\n\t\t\tThis is post 2 of 9 in the series <em>&ldquo;Signals&rdquo;<\/em>\t\t<\/p>\n\t\t\t<\/label>\n\n\t\t\t<div class=\"wp-post-series-box__posts\">\n\t\t\t<ol>\n\t\t\t\t\t\t\t\t\t<li><a href=\"https:\/\/www.angulararchitects.io\/en\/blog\/angular-signals\/\">Signals in Angular: Building Blocks<\/a><\/li>\n\t\t\t\t\t\t\t\t\t<li><span class=\"wp-post-series-box__current\">Component Communication with Signals: Inputs, Two-Way Bindings, and Content\/ View Queries<\/span><\/li>\n\t\t\t\t\t\t\t\t\t<li><a href=\"https:\/\/www.angulararchitects.io\/en\/blog\/successful-with-signals-in-angular-3-effective-rules-for-your-architecture\/\">Successful with Signals in Angular &#8211; 3 Effective Rules for Your Architecture<\/a><\/li>\n\t\t\t\t\t\t\t\t\t<li><a href=\"https:\/\/www.angulararchitects.io\/en\/blog\/skillfully-using-signals-in-angular-selected-hints-for-professional-use\/\">Skillfully Using Signals in Angular &#8211; Selected Hints for Professional Use<\/a><\/li>\n\t\t\t\t\t\t\t\t\t<li><a href=\"https:\/\/www.angulararchitects.io\/en\/blog\/when-not-to-use-effects-in-angular-and-what-to-do-instead\/\">When (Not) to use Effects in Angular &#8212; and what to do instead<\/a><\/li>\n\t\t\t\t\t\t\t\t\t<li><a href=\"https:\/\/www.angulararchitects.io\/en\/blog\/asynchronous-resources-with-angulars-new-resource-api\/\">Asynchronous Data Flow with Angular&#8217;s new Resource API<\/a><\/li>\n\t\t\t\t\t\t\t\t\t<li><a href=\"https:\/\/www.angulararchitects.io\/en\/blog\/streaming-resources-in-angular-19-2-details-and-semantics\/\">Streaming Resources in Angular &#8211; Details and Semantics<\/a><\/li>\n\t\t\t\t\t\t\t\t\t<li><a href=\"https:\/\/www.angulararchitects.io\/en\/blog\/streaming-resources-for-a-chat-with-web-sockets-messages-in-a-glitch-free-world\/\">Streaming Resources for a Chat with Web Sockets: Messages in a Glitch-Free World<\/a><\/li>\n\t\t\t\t\t\t\t\t\t<li><a href=\"https:\/\/www.angulararchitects.io\/en\/blog\/learning-httpresource-with-super-mario\/\">Angular&#8217;s new httpResource<\/a><\/li>\n\t\t\t\t\t\t\t<\/ol>\n\t\t<\/div>\n\t<\/div>\n<p>Signals will shape Angular's future. However, the Signals concept itself is just one part of the overall story. We also need a way to communicate with (sub)components via Signals. Angular 17.1 brought Input Signals, and with Angular 17.2 we've got Signal-based Two-way Bindings and support for content and view queries. To align with Input Signals, Version 17.3 provides a new output API.<\/p>\n<p>In this article, I show how to use these new possibilities.<\/p>\n<p>\ud83d\udcc1 <a href=\"https:\/\/github.com\/manfredsteyer\/signals-component-communication\">Source Code<\/a> (see different branches)<\/p>\n<blockquote>\n<p>Big thanks to Angular's <a href=\"@synalx\">Alex Rickabaugh<\/a> for an enlightening discussion about an idiomatic usage of Signals and to my awesome colleague <a href=\"https:\/\/twitter.com\/MikeZks\">Michael Egger-Zikes<\/a> for providing valuable feedback.<\/p>\n<\/blockquote>\n<h2>Input Signals<\/h2>\n<p>Inputs Signals allow us to receive data via Property Bindings in the form of Signals. For describing the usage of Signal Inputs, I'm using a simple <code>OptionComponent<\/code> representing a -- for the sake of simplicity -- non-selectable option. Here, three of them are presented:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2024\/02\/options.png\" alt=\"Three simple option components\" \/><\/p>\n<h3>Defining an Input Signal<\/h3>\n<p>Input Signals are the counterpart to the traditional @Input decorator:<\/p>\n<pre><code class=\"language-typescript\">@Component({\n  selector: &#039;app-option&#039;,\n  standalone: true,\n  imports: [],\n  template: `\n    &lt;div class=&quot;option&quot;&gt;\n      {{ label() }}\n    &lt;\/div&gt;\n  `,\n  styles: [...]\n})\nexport class OptionComponent {\n  label = input.required&lt;string&gt;();\n}<\/code><\/pre>\n<p>This <code>input<\/code> function is picked up by the Angular Compiler, emitting source code for property bindings. Hence, we should only use it together with properties. The other communication concepts discussed here also use this technique.<\/p>\n<p>Having a function instead of a decorator allows to inform TypeScript about the proper type and whether it includes <code>undefined<\/code>. In the example shown before, <code>label<\/code> becomes an <code>InputSignal&lt;string&gt;<\/code> -- an Input Signal providing a <code>string<\/code>. An <code>undefined<\/code> value is not possible as <code>input.required<\/code> defines a mandatory property.<\/p>\n<p>An <code>InputSignal<\/code> is always read-only and can be used like a <code>Signal<\/code>. The template above, for instance, requests its current value by calling the getter (<code>label()<\/code>).<\/p>\n<h3>Binding to an Input Signal<\/h3>\n<p>In the case of our <code>InputSignal&lt;string&gt;<\/code>, the caller has to pass a <code>string<\/code>:<\/p>\n<pre><code class=\"language-typescript\">&lt;app-option label=&quot;Option #1&quot;&gt;\n&lt;app-option [label]=&quot;myStringProperty&quot;&gt;<\/code><\/pre>\n<p>If this string comes from a Signal, we have to read it in the template:<\/p>\n<pre><code class=\"language-typescript\">&lt;app-option [label]=&quot;mySignalProperty()&quot;&gt;<\/code><\/pre>\n<h3>Computed Signals and Effects as a Replacement for Life Cycle Hooks<\/h3>\n<p>All changes to the passed Signal will be reflected by the <code>InputSignal<\/code> in the component. Internally, both Signals are connected via the graph Angular is maintaining. Life cycle hooks like <code>ngOnInit<\/code> and <code>ngOnChanges<\/code> can now be replaced with <code>computed<\/code> and <code>effect<\/code>:<\/p>\n<pre><code class=\"language-typescript\">markDownTitle = computed(() =&gt; &#039;# &#039; + this.label())\n\nconstructor() {\n  effect(() =&gt; {\n    console.log(&#039;label updated&#039;, this.label());\n    console.log(&#039;markdown&#039;, this.markDownTitle());\n  });\n}<\/code><\/pre>\n<h3>Options for Input Signals<\/h3>\n<p>Here are some further options for setting up an <code>InputSignal<\/code>:<\/p>\n<style>\nth {\n    border-bottom: 1px solid black;\n    text-align: left;\n} table {\n    margin-bottom: 40px;\n}\n<\/style>\n<table>\n<thead>\n<tr>\n<th>Source Code<\/th>\n<th>Description<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>label = input<string>();<\/td>\n<td>Optional property represented by an <code>InputSignal&lt;string                                                | undefined&gt;<\/code><\/td>\n<\/tr>\n<tr>\n<td>label = input('Hello');<\/td>\n<td>Optional property represented by an <code>InputSignal&lt;string&gt;<\/code> with an initial value of <code>Hello<\/code><\/td>\n<\/tr>\n<tr>\n<td>label = input&lt;string | undefined&gt;('Hello');<\/td>\n<td>Optional property represented by an <code>InputSignal&lt;string\\| undefined&gt;<\/code> with an initial value of <code>Hello<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3>Required Inputs Cannot Have a Default Value!<\/h3>\n<p>By definition, <code>input.required<\/code> cannot have a default value. This makes sense at first glance, however, there is a pitfall: If you try to read the value of a required input before it's been bound, Angular throws an exception.<\/p>\n<p>Hence, you cannot directly access it in the constructor. Instead, you can use <code>ngOnInit<\/code> or <code>ngOnChanges<\/code>. Also, using inputs within <code>computed<\/code> or <code>effect<\/code> is always safe, as they are only first triggered when the component has been initialized:<\/p>\n<pre><code class=\"language-typescript\">@Component([...])\nexport class OptionComponent implements OnInit, OnChanges {\n  label = input.required&lt;string&gt;();\n\n  \/\/ safe\n  markDownTitle = computed(() =&gt; &#039;# &#039; + this.label())\n\n  constructor() {\n    \/\/ this would cause an exception,\n    \/\/ as data hasn&#039;t been bound so far\n    console.log(&#039;label&#039;, this.label);\n\n    effect(() =&gt; {\n        \/\/ safe\n        console.log(&#039;label&#039;, this.label);\n    })\n  }\n\n  ngOnInit() {\n    \/\/ safe\n    console.log(&#039;label&#039;, this.label);\n  }\n\n  ngOnChanges() {\n    \/\/ safe\n    console.log(&#039;label&#039;, this.label);\n  }\n}<\/code><\/pre>\n<h3>Aliases for Input Signals<\/h3>\n<p>Both <code>input<\/code> and <code>input.require<\/code> also take a parameter object that allows the definition of an <code>alias<\/code>:<\/p>\n<pre><code class=\"language-typescript\">label = input.required({ alias: &quot;title&quot; });<\/code><\/pre>\n<p>In this case, the caller needs to bind to the property name defined by the alias:<\/p>\n<pre><code class=\"language-html\">&lt;app-option title=&quot;Option #1&quot;&gt;\n  &lt;app-option [title]=&quot;myStringProperty&quot;&gt;\n    &lt;app-option [title]=&quot;mySignalProperty()&quot;&gt;&lt;\/app-option&gt;&lt;\/app-option\n>&lt;\/app-option&gt;<\/code><\/pre>\n<p>In most cases, you should prevent the usage of aliases, as they create an unnecessary indirection. An often-seen exception to this rule is renaming one of a Directive's properties to match the configured attribute selector.<\/p>\n<h3>Transformer for Input Signals<\/h3>\n<p>Transformer have already been available for traditional @Inputs. They allow the transformation of a value passed via a property binding. In the following case, the transformer <code>booleanAttribute<\/code> that can be found in <code>angular\/core<\/code> is used:<\/p>\n<pre><code class=\"language-typescript\">@Component({\n  selector: &#039;app-option&#039;,\n  standalone: true,\n  imports: [],\n  template: `\n    &lt;div class=&quot;option&quot;&gt;\n      {{ label() }} @if (featured()) { \u2b50 }\n    &lt;\/div&gt;\n  `,\n  styles: [...]\n})\nexport class OptionComponent {\n  label = input.required&lt;string&gt;();\n  featured = input.required({\n    transform: booleanAttribute\n  })\n}<\/code><\/pre>\n<p>This transformer converts strings to booleans:<\/p>\n<pre><code class=\"language-html\">&lt;app-option label=&quot;Option #1&quot; featured=&quot;true&quot;&gt;&lt;\/app-option&gt;<\/code><\/pre>\n<p>Also, if the attribute is present but no value was assigned, <code>true<\/code> is assumed:<\/p>\n<pre><code class=\"language-html\">&lt;app-option label=&quot;Option #1&quot; featured&gt;&lt;\/app-option&gt;<\/code><\/pre>\n<p>This Signal's type is <code>InputSignal&lt;boolean, unknown&gt;<\/code>. The first type parameter (<code>boolean<\/code>) represents the value received from the transformer; the second one (<code>unknown<\/code>) is the value bound in the caller's template and passed to the transformer. Besides <code>booleanAttribute<\/code>, @angular\/core also provides a <code>numberAttribute<\/code> transformer that converts passed strings to numbers.<\/p>\n<p>If you want to implement a custom transformer, just provide a function taking the bound value and returning the value that should be used by the called component:<\/p>\n<pre><code class=\"language-typescript\">function boolTranformer(value: unknown): boolean {\n  return value !== &quot;no&quot;;\n}<\/code><\/pre>\n<p>Then, register this function in your <code>input<\/code>:<\/p>\n<pre><code class=\"language-typescript\">@Component([...])\nexport class OptionComponent {\n  label = input.required&lt;string&gt;();\n  featured = input.required({\n    transform: boolTranformer\n  })\n}<\/code><\/pre>\n<h2>Two-Way Data Binding with Model Signals<\/h2>\n<p>Input Signals are read-only. If you want to pass a Signal that can be updated by the called component, you need to set up a so-called Model Signal. To demonstrate this, I'm using a simple <code>TabbedPaneComponent<\/code>:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2024\/02\/tabs.png\" alt=\"TabbedPane\" \/><\/p>\n<p>This is how the consumer can use this component:<\/p>\n<pre><code class=\"language-html\">&lt;app-tabbed-pane [(current)]=&quot;current&quot;&gt;\n  &lt;app-tab title=&quot;1st tab&quot;&gt; Lorem, ipsum dolor sit amet ... &lt;\/app-tab&gt;\n  &lt;app-tab title=&quot;2nd tab&quot;&gt; Sammas ergo gemma, ipsum dolor ... &lt;\/app-tab&gt;\n  &lt;app-tab title=&quot;3nd tab&quot;&gt; Gemma ham ipsum dolor sit ... &lt;\/app-tab&gt;\n&lt;\/app-tabbed-pane&gt;\n\n&lt;p class=&quot;current-info&quot;&gt;Current: {{ current() }}&lt;\/p&gt;<\/code><\/pre>\n<p>It gets several <code>TabComponent<\/code>s passed. Also, a Signal <code>current<\/code> is bound via a Two-way Binding. For allowing this, the <code>TabbedPaneComponent<\/code> needs to provide a Model Signal using <code>model<\/code>:<\/p>\n<pre><code class=\"language-typescript\">@Component([...])\nexport class TabbedPaneComponent {\n  current = model(0);\n  [...]\n}<\/code><\/pre>\n<p>Here, <code>0<\/code> is the initial value. The options are similar to the ones for input: <code>model.required<\/code> defines a mandatory property, and you can provide an alias via an options object. However, a transformer can not be defined.<\/p>\n<p>If this component updates the Model Signal, the new value is propagated up to the the Signal bound in the template:<\/p>\n<pre><code class=\"language-typescript\">current.set(1);<\/code><\/pre>\n<h3>Two-Way Data Binding as Combination of Input and Output<\/h3>\n<p>As usual in Angular, also Signal-based Two-way Bindings can be defined with a (read-only) Input and a respective Output. The Output's name must be the Input's name with the suffix <code>Change<\/code>. Hence, for <code>current<\/code> we need to define <code>currentChange<\/code>:<\/p>\n<pre><code class=\"language-typescript\">@Component([...])\nexport class TabbedPaneComponent {\n  current = input(0);\n  currentChange = output&lt;number&gt;();\n}<\/code><\/pre>\n<p>For setting up an Output, we the new output API is used. For triggering an event, the application has to call the output's <code>emit<\/code> method:<\/p>\n<pre><code class=\"language-html\">&lt;button [...] (click)=&quot;currentChange.emit($index)&quot;&gt;{{tab.title()}}&lt;\/button&gt;<\/code><\/pre>\n<h2>Content Queries with Signals<\/h2>\n<p>The <code>TabbedPaneComponent<\/code> introduced in the previous section also allows us to showcase another option: Content Queries that get hold of projected Components or Directives.<\/p>\n<p>As shown above, a <code>TabbedPaneComponent<\/code> gets several <code>TabComponents<\/code> passed. They are projected into the <code>TabbedPaneComponent<\/code>'s view. However, we only want to display one of them at a given time. Hence, the <code>TabbedPaneComponent<\/code> needs to get programmatic access to its <code>TabComponents<\/code>. This can be done with the new <code>contentChildren<\/code> function:<\/p>\n<pre><code class=\"language-typescript\">@Component({\n  selector: &#039;app-tabbed-pane&#039;,\n  standalone: true,\n  imports: [],\n  template: `\n    &lt;div class=&quot;pane&quot;&gt;\n      &lt;div class=&quot;nav&quot; role=&quot;group&quot;&gt;\n        @for(tab of tabs(); track tab) {\n        &lt;button\n            [class.secondary]=&quot;tab !== currentTab()&quot;\n            (click)=&quot;activate($index)&quot;&gt;\n                {{tab.title()}}\n        &lt;\/button&gt;\n        }\n      &lt;\/div&gt;\n      &lt;article&gt;\n        &lt;ng-content&gt;&lt;\/ng-content&gt;\n      &lt;\/article&gt;\n    &lt;\/div&gt;\n  `,\n  styles: [...]\n})\nexport class TabbedPaneComponent {\n  current = model(0);\n  tabs = contentChildren(TabComponent);\n  currentTab = computed(() =&gt; this.tabs()[this.current()]);\n\n  activate(active: number): void {\n    this.current.set(active);\n  }\n}<\/code><\/pre>\n<p>The function <code>contentChildren<\/code> is the counterpart to the traditional @ContentChildren decorator. As <code>TabComponent<\/code> was passed as a so-called <code>locator<\/code>, it returns a Signal with an Array holding all projected <code>TabComponent<\/code>s.<\/p>\n<p>Having the projected nodes as a Signal allows us to project them using <code>computed<\/code> reactively. The shown example uses this option to derive a Signal <code>currentTab<\/code>.<\/p>\n<p>The projected <code>TabComponent<\/code> uses this Signal to find out whether it should be visible:<\/p>\n<pre><code class=\"language-typescript\">@Component({\n  selector: &quot;app-tab&quot;,\n  standalone: true,\n  imports: [],\n  template: `\n    @if(visible()) {\n    &lt;div class=&quot;tab&quot;&gt;\n      &lt;h2&gt;{{ title() }}&lt;\/h2&gt;\n      &lt;ng-content&gt;&lt;\/ng-content&gt;\n    &lt;\/div&gt;\n    }\n  `,\n})\nexport class TabComponent {\n  pane = inject(TabbedPaneComponent);\n\n  title = input.required&lt;string&gt;();\n\n  visible = computed(() =&gt; this.pane.currentTab() === this);\n}<\/code><\/pre>\n<p>For this, we need to know that we can get all parents located in the DOM via dependency injection. The <code>visible<\/code> Signal is derived from the <code>currentTab<\/code> Signal.<\/p>\n<p>This procedure is usual in the reactive world: Instead of imperatively setting values, they are declaratively derived from other values.<\/p>\n<h3>Content Queries for Descendants<\/h3>\n<p>By default, a Content Query only unveils direct content children. &quot;Grandchildren&quot;, like the 3rd tab below, are ignored:<\/p>\n<pre><code class=\"language-html\">&lt;app-tabbed-pane [(current)]=&quot;current&quot;&gt;\n  &lt;app-tab title=&quot;1st tab&quot;&gt; Lorem, ipsum dolor sit amet ... &lt;\/app-tab&gt;\n  &lt;app-tab title=&quot;2nd tab&quot;&gt; Sammas ergo gemma, ipsum dolor ... &lt;\/app-tab&gt;\n\n  &lt;div class=&quot;danger-zone&quot;&gt;\n    &lt;app-tab title=&quot;3nd tab&quot;&gt;\n      Here, you can delete the whole internet!\n    &lt;\/app-tab&gt;\n  &lt;\/div&gt;\n&lt;\/app-tabbed-pane&gt;<\/code><\/pre>\n<p>To also get hold of such nodes, we can set the option <code>descendants<\/code> to <code>true<\/code>:<\/p>\n<pre><code class=\"language-typescript\">tabs = contentChildren(TabComponent, { descendants: true });<\/code><\/pre>\n<h2>Output API<\/h2>\n<p>For the sake of API symmetricity, Angular 17.3 introduced a new output API. As already shown before, an <code>output<\/code> function is now used for defining an event provided by a component. Similar to the new input API, the Angular Compiler picks up the call to the <code>output<\/code> and emits respective code. The returned <code>OutputEmitterRef<\/code>'s <code>emit<\/code> method is used to trigger the event:<\/p>\n<pre><code class=\"language-typescript\">@Component([...])\nexport class TabbedPaneComponent {\n  current = model(0);\n  tabs = contentChildren(TabComponent);\n  currentTab = computed(() =&gt; this.tabs()[this.current()]);\n\n  tabActivated = output&lt;TabActivatedEvent&gt;();\n\n  activate(active: number): void {\n    const previous = this.current();\n    this.current.set(active);\n    this.tabActivated.emit({ previous, active });\n  }\n}<\/code><\/pre>\n<h3>Providing Observables as Outputs<\/h3>\n<p>Besides this simple way of setting up outputs, you can use an Observable as the source for an output. For this, you find a function <code>outputFromObservable<\/code> in the RxJS interop layer:<\/p>\n<pre><code class=\"language-typescript\">import { \n    outputFromObservable, \n    toObservable \n} from &#039;@angular\/core\/rxjs-interop&#039;;\n[...]\n\n@Component([...])\nexport class TabbedPaneComponent {\n  current = model(0);\n  tabs = contentChildren(TabComponent);\n  currentTab = computed(() =&gt; this.tabs()[this.current()]);\n\n  tabChanged$ = toObservable(this.current).pipe(\n    scan(\n      (acc, active) =&gt; ({ active, previous: acc.active }),\n      { active: -1, previous: -1 }\n    ),\n    skip(1),\n  );\n\n  tabChanged = outputFromObservable(this.tabChanged$);\n\n  activate(active: number): void {\n    this.current.set(active);\n  }\n\n}<\/code><\/pre>\n<p>The function <code>outputFromObservable<\/code> converts an Observable to an <code>OutputEmitterRef<\/code>. In the shown example, the <code>scan<\/code> operator remembers the previous activated tab and <code>skip<\/code> ensures that no event is emitted when initially setting <code>current<\/code>. The latter one provides feature parity with the before-shown example.<\/p>\n<h2>View Queries with Signals<\/h2>\n<p>While a Content Query returns projected nodes, a View Query returns nodes from its own view. These are nodes found in the template of the respective component. In most cases, using data binding instead is the preferable solution. However, getting programmatic access to a view child is needed in some situations.<\/p>\n<p>To demonstrate how to query view children, I use a simple form for setting a username and a password:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2024\/02\/form.png\" alt=\"Form for setting username and password\" \/><\/p>\n<p>Both <code>input<\/code> fields are marked as <code>required<\/code>. If the validation fails when pressing <code>Save<\/code>, the first field with a validation error should get the focus. For this, we need access to the <code>NgForm<\/code> directive the <code>FormModule<\/code> adds to our <code>form<\/code> tag as well as to the DOM nodes representing the <code>input<\/code> fields:<\/p>\n<pre><code class=\"language-typescript\">@Component({\n  selector: &quot;app-form&quot;,\n  standalone: true,\n  imports: [FormsModule, JsonPipe],\n  template: `\n    &lt;h1&gt;Form Demo&lt;\/h1&gt;\n    &lt;form autocomplete=&quot;off&quot;&gt;\n      &lt;input\n        [(ngModel)]=&quot;userName&quot;\n        placeholder=&quot;User Name&quot;\n        name=&quot;userName&quot;\n        #userNameCtrl\n        required\n      \/&gt;\n      &lt;input\n        [(ngModel)]=&quot;password&quot;\n        placeholder=&quot;Password&quot;\n        type=&quot;password&quot;\n        name=&quot;password&quot;\n        #passwordCtrl\n        required\n      \/&gt;\n      &lt;button (click)=&quot;save()&quot;&gt;Save&lt;\/button&gt;\n    &lt;\/form&gt;\n  `,\n  styles: `\n    form {\n      max-width: 600px;\n    }\n  `,\n})\nexport class FormDemoComponent {\n  form = viewChild.required(NgForm);\n\n  userNameCtrl =\n    viewChild.required&lt;ElementRef&lt;HTMLInputElement&gt;&gt;(&quot;userNameCtrl&quot;);\n  passwordCtrl =\n    viewChild.required&lt;ElementRef&lt;HTMLInputElement&gt;&gt;(&quot;passwordCtrl&quot;);\n\n  userName = signal(&quot;&quot;);\n  password = signal(&quot;&quot;);\n\n  save(): void {\n    const form = this.form();\n\n    if (form.controls[&quot;userName&quot;].invalid) {\n      this.userNameCtrl().nativeElement.focus();\n      return;\n    }\n\n    if (form.controls[&quot;password&quot;].invalid) {\n      this.passwordCtrl().nativeElement.focus();\n      return;\n    }\n\n    console.log(&quot;save&quot;, this.userName(), this.password());\n  }\n}<\/code><\/pre>\n<p>Both are done using the <code>viewChild<\/code> function. In the first case, the example passes the type <code>NgForm<\/code> as the locator. However, just locating the fields with a type does not work, as there might be several children with this type. For this reason, the inputs are marked with handles (<code>#userName<\/code> and <code>#password<\/code>), and the respective handle's name is passed the locator.<\/p>\n<p>View children can be represented by different types: The type of the respective Component or Directive, an <code>ElementRef<\/code> representing its DOM node, or a <code>ViewContainerRef<\/code>. The latter one is used in the next section.<\/p>\n<p>The desired type can be mentioned using the <code>read<\/code> option used in the previous example.<\/p>\n<h2>Queries and ViewContainerRef<\/h2>\n<p>There are situations where you need to dynamically add a component to a placeholder. Examples are modal dialogs or toasts. An easy way to achieve this is using the <code>*ngComponentOutlet<\/code> directive. A more flexible way is querying the <code>ViewContainerRef<\/code> of the placeholder.<\/p>\n<p>You can think about a View Container as an invisible container around each Component and piece of static HTML. After getting hold of it, you can add further Components or Templates.<\/p>\n<p>To demonstrate this, I'm using a simple example showing a toast:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2024\/02\/toast.png\" alt=\"Example displaying a toast\" \/><\/p>\n<p>The example uses an <code>ng-container<\/code> as a placeholder:<\/p>\n<pre><code class=\"language-typescript\">@Component({\n  selector: &#039;app-dynamic&#039;,\n  standalone: true,\n  imports: [],\n  template: `\n    &lt;h2&gt;Toast Demo&lt;\/h2&gt;\n    &lt;button (click)=&quot;show()&quot;&gt;Show Toast&lt;\/button&gt;\n    &lt;ng-container #placeholder&gt;&lt;\/ng-container&gt;\n  `,\n  styles: [...]\n})\nexport class ToastDemoComponent {\n  counter = 0;\n  placeholder = viewChild.required(&#039;placeholder&#039;, { read: ViewContainerRef });\n\n  show() {\n    const ref = this.placeholder()?.createComponent(ToastComponent);\n    this.counter++;\n    ref?.setInput(&#039;label&#039;, &#039;Message #&#039; + this.counter);\n    setTimeout(() =&gt; ref?.destroy(), 2000);\n  }\n\n}<\/code><\/pre>\n<p>The <code>read<\/code> property makes clear that we don't want to read the placeholder component but it's <code>ViewContainerRef<\/code>. The <code>createComponent<\/code> method instantiates and adds a <code>ToastComponent<\/code>. The returned <code>ComponentRef<\/code> is used to set the new component's <code>label<\/code> property. For this, its <code>setInput<\/code> method is used. After two seconds, the <code>destroy<\/code> method removes the toast again.<\/p>\n<p>For the sake of simplicity, the component <code>ToastComponent<\/code> was hard-coded here. In more generic real-world scenarios, the component to use can be configured, e.g., by calling a service method, taking the Component type, and notifying another Component that adds a Component of this type to a placeholder.<\/p>\n<h3>Programmatically Setting up an Output<\/h3>\n<p>The previous example called <code><code>setInput<\/code><code> for assigning a value to the <\/code>ToastComponent<code>&#039;s <\/code>title<\/code> input. Here, I want to discuss how to define event handlers for such dynamically added components.<\/p>\n<p>Let's assume, the <code>ToastComponent<\/code> shows a confirmation link:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2024\/03\/toast-with-confirm-link.png\" alt=\"Toast with confirm link\" \/><\/p>\n<p>When clicking this link, it emits an <code>confirmed<\/code> event:<\/p>\n<pre><code class=\"language-typescript\">@Component([...])\nexport class ToastComponent {\n  label = input.required&lt;string&gt;();\n  confirmed = output&lt;string&gt;();\n\n  confirm(): void {\n    this.confirmed.emit(this.label());\n  }\n}<\/code><\/pre>\n<p>To set up an handler for this event, we can directly use the returned <code>ComponentRef<\/code>'s <code><code>instance<\/code><\/code> property. It points to the added component instance and hence provides access to all its properties:<\/p>\n<pre><code class=\"language-typescript\">@Component([...])\nexport class ToastDemoComponent {\n  counter = 0;\n  placeholder = viewChild.required(&#039;placeholder&#039;, { read: ViewContainerRef });\n\n  show() {\n    const ref = this.placeholder()?.createComponent(ToastComponent);\n    this.counter++;\n    const title = &#039;Message #&#039; + this.counter;\n    ref.setInput(&#039;label&#039;, title);\n\n    \/\/ Event handler for confirm output\n    ref.instance.confirmed.subscribe(title =&gt; {\n      ref?.destroy();\n      console.log(&#039;confirmed&#039;, title);\n    });\n\n    setTimeout(() =&gt; ref?.destroy(), 5000);\n  }\n\n}<\/code><\/pre>\n<p>The <code>OutputEmitterRef<\/code>'s <code>subscribe<\/code> method allows to define an event handler. In our case, it just removes the toast using <code>destroy<\/code> and logs the received string to the console.<\/p>\n<p>However, this example comes with a small beauty mistake. Regardless whether the user clicks the confirmation link or not, the example calls <code>destroy<\/code> after 5 seconds. Hence, the toast might be removed twice: Once after the confirmation and another time after displaying it for 5 seconds. <\/p>\n<p>Fortunately, destroying a component twice does not result in an error. To solve this, we could introduce a <code>destroyed<\/code> flag . The next section shows a more powerful approach: Consuming outputs as Observables.<\/p>\n<h3>Consuming Outputs as Observables<\/h3>\n<p>Even though the <code>OutputEmitterRef<\/code> provides a <code>subscribe<\/code> method, it is not an Observable. However, the original <code>EventEmitter<\/code> used together with the @Output decorator was. To get back all the possibilities associated with Observable-based outputs, you can use the function <code>outputToObservable<\/code> that is part of the RxJS interop layer:<\/p>\n<pre><code class=\"language-typescript\">import { outputToObservable } from &#039;@angular\/core\/rxjs-interop&#039;;\n[...]\n\n@Component([...])\nexport class ToastDemoComponent {\n  counter = 0;\n  placeholder = viewChild.required(&#039;placeholder&#039;, { read: ViewContainerRef });\n\n  show() {\n    const ref = this.placeholder()?.createComponent(ToastComponent);\n    this.counter++;\n    const title = &#039;Message #&#039; + this.counter;\n    ref.setInput(&#039;label&#039;, title);\n\n    const confirmed$ = outputToObservable(ref.instance.confirmed)\n      .pipe(map(title =&gt; ({ trigger: &#039;confirmed&#039;, title })));\n\n    const timer$ = timer(5000);\n      .pipe(map(() =&gt; ({ trigger: &#039;timeout&#039;, title })));\n\n    race(confirmed$, timer$).subscribe(action =&gt; {\n      ref?.destroy();\n      console.log(&#039;action&#039;, action);\n    });\n\n  }\n\n}<\/code><\/pre>\n<p>The function <code>outputToObservable<\/code> converts an <code>OutputEmitterRef<\/code> to an Observable. The shown example uses it to express both, the confirm event and the 5 sec timeout as observable. The <code>race<\/code> operator ensures that only the Observable that first issues a value is used.<\/p>\n<p>The Observable returned by <code>outputToObservable<\/code> completes when Angular destroys the the output's component. For this reason, there is no need to unsubscribe by hand. <\/p>\n<h2>Feature Parity between Content and View Queries<\/h2>\n<p>So far, we have worked with <code>contentChildren<\/code> to query several projected children and <code>viewChild<\/code> to get hold of one node in the view. However, both concepts have feature parity: For instance, there is also a <code>contentChild<\/code> and a <code>viewChildren<\/code> function.<\/p>\n<p>Also, all the options we've used above for View or Content Queries, like using handles as locators or using the <code>read<\/code> property, work for both kinds of queries. <\/p>\n<h2>Conclusion<\/h2>\n<p>Several new functions replace property decorators and help to set up data binding concepts. These functions are picked up by the Angular compiler emitting respective code.<\/p>\n<p>The function <code>input<\/code> defines Inputs for property bindings, <code>model<\/code> defines Inputs for Two Way Data Binding, and <code>contentChild(ren)<\/code> and <code>viewChild(ren)<\/code> take care of Content and View Queries. Using these functions results in Signals that can be projected with <code>computed<\/code> and used within effects.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This is post 2 of 9 in the series &ldquo;Signals&rdquo; Signals in Angular: Building Blocks Component Communication with Signals: Inputs, Two-Way Bindings, and Content\/ View Queries Successful with Signals in Angular &#8211; 3 Effective Rules for Your Architecture Skillfully Using Signals in Angular &#8211; Selected Hints for Professional Use When (Not) to use Effects in [&hellip;]<\/p>\n","protected":false},"author":25,"featured_media":24787,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_price":"","_stock":"","_tribe_ticket_header":"","_tribe_default_ticket_provider":"","_ticket_start_date":"","_ticket_end_date":"","_tribe_ticket_show_description":"","_tribe_ticket_show_not_going":false,"_tribe_ticket_use_global_stock":"","_tribe_ticket_global_stock_level":"","_global_stock_mode":"","_global_stock_cap":"","_tribe_rsvp_for_event":"","_tribe_ticket_going_count":"","_tribe_ticket_not_going_count":"","_tribe_tickets_list":"[]","_tribe_ticket_has_attendee_info_fields":false,"footnotes":""},"categories":[18],"tags":[],"class_list":["post-24793","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized","post_series-signals"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.1.1 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Component Communication with Signals: Inputs, Two-Way Bindings, and Content\/ View Queries - ANGULARarchitects<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.angulararchitects.io\/en\/blog\/component-communication-with-signals-inputs-two-way-bindings-and-content-view-queries\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Component Communication with Signals: Inputs, Two-Way Bindings, and Content\/ View Queries - ANGULARarchitects\" \/>\n<meta property=\"og:description\" content=\"This is post 2 of 9 in the series &ldquo;Signals&rdquo; Signals in Angular: Building Blocks Component Communication with Signals: Inputs, Two-Way Bindings, and Content\/ View Queries Successful with Signals in Angular &#8211; 3 Effective Rules for Your Architecture Skillfully Using Signals in Angular &#8211; Selected Hints for Professional Use When (Not) to use Effects in [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.angulararchitects.io\/en\/blog\/component-communication-with-signals-inputs-two-way-bindings-and-content-view-queries\/\" \/>\n<meta property=\"og:site_name\" content=\"ANGULARarchitects\" \/>\n<meta property=\"article:published_time\" content=\"2024-02-12T11:05:51+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2024-03-07T17:27:43+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2024\/02\/sujet.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1000\" \/>\n\t<meta property=\"og:image:height\" content=\"500\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Manfred Steyer\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:image\" content=\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2024\/02\/sujet.png\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Manfred Steyer\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"16 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/component-communication-with-signals-inputs-two-way-bindings-and-content-view-queries\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/component-communication-with-signals-inputs-two-way-bindings-and-content-view-queries\/\"},\"author\":{\"name\":\"Manfred Steyer\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/f3de69c1e2bdb5ba04d8d2f5f998b81a\"},\"headline\":\"Component Communication with Signals: Inputs, Two-Way Bindings, and Content\/ View Queries\",\"datePublished\":\"2024-02-12T11:05:51+00:00\",\"dateModified\":\"2024-03-07T17:27:43+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/component-communication-with-signals-inputs-two-way-bindings-and-content-view-queries\/\"},\"wordCount\":2076,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/component-communication-with-signals-inputs-two-way-bindings-and-content-view-queries\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2024\/02\/shutterstock_573678820.jpg\",\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.angulararchitects.io\/en\/blog\/component-communication-with-signals-inputs-two-way-bindings-and-content-view-queries\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/component-communication-with-signals-inputs-two-way-bindings-and-content-view-queries\/\",\"url\":\"https:\/\/www.angulararchitects.io\/en\/blog\/component-communication-with-signals-inputs-two-way-bindings-and-content-view-queries\/\",\"name\":\"Component Communication with Signals: Inputs, Two-Way Bindings, and Content\/ View Queries - ANGULARarchitects\",\"isPartOf\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/component-communication-with-signals-inputs-two-way-bindings-and-content-view-queries\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/component-communication-with-signals-inputs-two-way-bindings-and-content-view-queries\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2024\/02\/shutterstock_573678820.jpg\",\"datePublished\":\"2024-02-12T11:05:51+00:00\",\"dateModified\":\"2024-03-07T17:27:43+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/component-communication-with-signals-inputs-two-way-bindings-and-content-view-queries\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.angulararchitects.io\/en\/blog\/component-communication-with-signals-inputs-two-way-bindings-and-content-view-queries\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/component-communication-with-signals-inputs-two-way-bindings-and-content-view-queries\/#primaryimage\",\"url\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2024\/02\/shutterstock_573678820.jpg\",\"contentUrl\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2024\/02\/shutterstock_573678820.jpg\",\"width\":1000,\"height\":667},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/component-communication-with-signals-inputs-two-way-bindings-and-content-view-queries\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.angulararchitects.io\/en\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Component Communication with Signals: Inputs, Two-Way Bindings, and Content\/ View Queries\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#website\",\"url\":\"https:\/\/www.angulararchitects.io\/en\/\",\"name\":\"ANGULARarchitects\",\"description\":\"AngularArchitects.io\",\"publisher\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.angulararchitects.io\/en\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#organization\",\"name\":\"ANGULARarchitects\",\"alternateName\":\"SOFTWAREarchitects\",\"url\":\"https:\/\/www.angulararchitects.io\/en\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2023\/07\/AA-Logo-RGB-horizontal-inside-knowledge-black.svg\",\"contentUrl\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2023\/07\/AA-Logo-RGB-horizontal-inside-knowledge-black.svg\",\"width\":644,\"height\":216,\"caption\":\"ANGULARarchitects\"},\"image\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/github.com\/angular-architects\",\"https:\/\/www.linkedin.com\/company\/angular-architects\/\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/f3de69c1e2bdb5ba04d8d2f5f998b81a\",\"name\":\"Manfred Steyer\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/8778dfb353992fa3a0d909beee085a088891e5bfce65cdb3631801da527cf11b?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/8778dfb353992fa3a0d909beee085a088891e5bfce65cdb3631801da527cf11b?s=96&d=mm&r=g\",\"caption\":\"Manfred Steyer\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Component Communication with Signals: Inputs, Two-Way Bindings, and Content\/ View Queries - ANGULARarchitects","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.angulararchitects.io\/en\/blog\/component-communication-with-signals-inputs-two-way-bindings-and-content-view-queries\/","og_locale":"en_US","og_type":"article","og_title":"Component Communication with Signals: Inputs, Two-Way Bindings, and Content\/ View Queries - ANGULARarchitects","og_description":"This is post 2 of 9 in the series &ldquo;Signals&rdquo; Signals in Angular: Building Blocks Component Communication with Signals: Inputs, Two-Way Bindings, and Content\/ View Queries Successful with Signals in Angular &#8211; 3 Effective Rules for Your Architecture Skillfully Using Signals in Angular &#8211; Selected Hints for Professional Use When (Not) to use Effects in [&hellip;]","og_url":"https:\/\/www.angulararchitects.io\/en\/blog\/component-communication-with-signals-inputs-two-way-bindings-and-content-view-queries\/","og_site_name":"ANGULARarchitects","article_published_time":"2024-02-12T11:05:51+00:00","article_modified_time":"2024-03-07T17:27:43+00:00","og_image":[{"width":1000,"height":500,"url":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2024\/02\/sujet.png","type":"image\/png"}],"author":"Manfred Steyer","twitter_card":"summary_large_image","twitter_image":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2024\/02\/sujet.png","twitter_misc":{"Written by":"Manfred Steyer","Est. reading time":"16 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.angulararchitects.io\/en\/blog\/component-communication-with-signals-inputs-two-way-bindings-and-content-view-queries\/#article","isPartOf":{"@id":"https:\/\/www.angulararchitects.io\/en\/blog\/component-communication-with-signals-inputs-two-way-bindings-and-content-view-queries\/"},"author":{"name":"Manfred Steyer","@id":"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/f3de69c1e2bdb5ba04d8d2f5f998b81a"},"headline":"Component Communication with Signals: Inputs, Two-Way Bindings, and Content\/ View Queries","datePublished":"2024-02-12T11:05:51+00:00","dateModified":"2024-03-07T17:27:43+00:00","mainEntityOfPage":{"@id":"https:\/\/www.angulararchitects.io\/en\/blog\/component-communication-with-signals-inputs-two-way-bindings-and-content-view-queries\/"},"wordCount":2076,"commentCount":0,"publisher":{"@id":"https:\/\/www.angulararchitects.io\/en\/#organization"},"image":{"@id":"https:\/\/www.angulararchitects.io\/en\/blog\/component-communication-with-signals-inputs-two-way-bindings-and-content-view-queries\/#primaryimage"},"thumbnailUrl":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2024\/02\/shutterstock_573678820.jpg","inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.angulararchitects.io\/en\/blog\/component-communication-with-signals-inputs-two-way-bindings-and-content-view-queries\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.angulararchitects.io\/en\/blog\/component-communication-with-signals-inputs-two-way-bindings-and-content-view-queries\/","url":"https:\/\/www.angulararchitects.io\/en\/blog\/component-communication-with-signals-inputs-two-way-bindings-and-content-view-queries\/","name":"Component Communication with Signals: Inputs, Two-Way Bindings, and Content\/ View Queries - ANGULARarchitects","isPartOf":{"@id":"https:\/\/www.angulararchitects.io\/en\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.angulararchitects.io\/en\/blog\/component-communication-with-signals-inputs-two-way-bindings-and-content-view-queries\/#primaryimage"},"image":{"@id":"https:\/\/www.angulararchitects.io\/en\/blog\/component-communication-with-signals-inputs-two-way-bindings-and-content-view-queries\/#primaryimage"},"thumbnailUrl":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2024\/02\/shutterstock_573678820.jpg","datePublished":"2024-02-12T11:05:51+00:00","dateModified":"2024-03-07T17:27:43+00:00","breadcrumb":{"@id":"https:\/\/www.angulararchitects.io\/en\/blog\/component-communication-with-signals-inputs-two-way-bindings-and-content-view-queries\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.angulararchitects.io\/en\/blog\/component-communication-with-signals-inputs-two-way-bindings-and-content-view-queries\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.angulararchitects.io\/en\/blog\/component-communication-with-signals-inputs-two-way-bindings-and-content-view-queries\/#primaryimage","url":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2024\/02\/shutterstock_573678820.jpg","contentUrl":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2024\/02\/shutterstock_573678820.jpg","width":1000,"height":667},{"@type":"BreadcrumbList","@id":"https:\/\/www.angulararchitects.io\/en\/blog\/component-communication-with-signals-inputs-two-way-bindings-and-content-view-queries\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.angulararchitects.io\/en\/"},{"@type":"ListItem","position":2,"name":"Component Communication with Signals: Inputs, Two-Way Bindings, and Content\/ View Queries"}]},{"@type":"WebSite","@id":"https:\/\/www.angulararchitects.io\/en\/#website","url":"https:\/\/www.angulararchitects.io\/en\/","name":"ANGULARarchitects","description":"AngularArchitects.io","publisher":{"@id":"https:\/\/www.angulararchitects.io\/en\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.angulararchitects.io\/en\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.angulararchitects.io\/en\/#organization","name":"ANGULARarchitects","alternateName":"SOFTWAREarchitects","url":"https:\/\/www.angulararchitects.io\/en\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.angulararchitects.io\/en\/#\/schema\/logo\/image\/","url":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2023\/07\/AA-Logo-RGB-horizontal-inside-knowledge-black.svg","contentUrl":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2023\/07\/AA-Logo-RGB-horizontal-inside-knowledge-black.svg","width":644,"height":216,"caption":"ANGULARarchitects"},"image":{"@id":"https:\/\/www.angulararchitects.io\/en\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/github.com\/angular-architects","https:\/\/www.linkedin.com\/company\/angular-architects\/"]},{"@type":"Person","@id":"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/f3de69c1e2bdb5ba04d8d2f5f998b81a","name":"Manfred Steyer","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/8778dfb353992fa3a0d909beee085a088891e5bfce65cdb3631801da527cf11b?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/8778dfb353992fa3a0d909beee085a088891e5bfce65cdb3631801da527cf11b?s=96&d=mm&r=g","caption":"Manfred Steyer"}}]}},"_links":{"self":[{"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/posts\/24793","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/users\/25"}],"replies":[{"embeddable":true,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/comments?post=24793"}],"version-history":[{"count":10,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/posts\/24793\/revisions"}],"predecessor-version":[{"id":25232,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/posts\/24793\/revisions\/25232"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/media\/24787"}],"wp:attachment":[{"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/media?parent=24793"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/categories?post=24793"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/tags?post=24793"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}