Update 2
A version with checkboxes:
Stackblitz demo with checkboxes
- creates a component holding the two checkboxes of a pair
- passes as @Input() the pair object
- handled the (change) event on each of the checkboxes
- create an @Output() event on the component, and when a checkbox was clicked, raise an event to the parent component with the payload ("first" or "second" or null) depending on what selection was made
See more on component interaction via Input-Output here.
A screenshot of the result:

Update 1
For your case, radio buttons are recommended. If you can use them, you won't need a custom control.
See stackblitz demo

To keep it simple, I am using input radio buttons in a template-based form (it's simpler that using a reactive form).
As you want to select only one of each pair, then:
- each pair of radio buttons must be in their own radio buttons group (using input "name" attribute).
Here you must have a unique group name per pair. For example, the current object's key and the index of the pair in the choice list on that key, like that:
[name]="'resolution' + '_' + choice.key + '_' + index"
- each pair of radio buttons must be bound to their own variable. The variable says which one of the two buttons was selected. We use [(ngModel)] (two way binding) for binding the variable. For example you could use choiceList (which is the current pair) and just add a property "selected" with the currently selected item of the pair:
[(ngModel)]="choiceList.resolution"
To sum up the two conditions, the two inputs can be:
<input type="radio" [name]="'resolution' + '_' + choice.key + '_' + index" value="first" [(ngModel)]="choiceList.resolution" />
<input type="radio" [name]="'resolution' + '_' + choice.key + '_' + index" value="second" [(ngModel)]="choiceList.resolution" />
Only the "value" attributes differs between the inputs (first|second), as you need to know which one is selected; the selected value will be found in choiceList.resolution variable.
See the full code below:
app.component.html
<div>
<div *ngFor="let choice of sample | keyvalue">
<div *ngFor="let choiceList of choice.value; let index = index">
<p>Key = {{choice.key}}. Index = {{index}}</p>
<form>
<div class="firstChoice">
<div class="existingRule">
<label>
<input type="radio" [name]="'resolution' + '_' + choice.key + '_' + index" value="first"
[(ngModel)]="choiceList.resolution" />
{{choiceList.first}}
</label>
</div>
</div>
<div class="ruleSeparator"> OR </div>
<div class="secondChoice">
<div class="updatedRule">
<label>
<input type="radio" [name]="'resolution' + '_' + choice.key + '_' + index" value="second"
[(ngModel)]="choiceList.resolution" />
{{choiceList.second}}
</label>
</div>
</div>
<p>
The choice is: <b>{{ choiceList.resolution }}</b>
</p>
</form>
</div>
<hr>
</div>
</div>
app.component.ts
import { Component } from '@angular/core';
import { ReactiveFormsModule, FormBuilder, FormGroup, Validators } from '@angular/forms';
export interface Choice {
first: string,
second: string,
selected: string
}
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
form: FormGroup;
sample;
constructor(fb: FormBuilder) {
this.sample = {
"first": [{
"first":"first_first",
"second":"first_second"
//here we bind a new property "selected" which will contain which selection was made (first|second)
}],
"second": [{
"first": "second_first",
"second": "second_second"
//"selected": "first" | "second" (=> based on selection in the form)
}, {
"first": "second_third",
"second": "second_forth"
//"selected": "first" | "second" (=> based on selection in the form)
}]
};
}
}
You can define the object directly as JSON, as I did above for sample. You used Map<string,Choice[]>, but there is no need to use an explicit Map, all objects are key-value maps in Javascript. To add a new property to the map, you could just say
let key = 'your key'; // I suppose you generate the key programatically
this.sample[key] = [{first: "", second: ""}];