Докато надграждате върху angular, независимо дали е широкомащабно корпоративно приложение или просто малък страничен проект, определено ще се окажете в етап с изискване за двупосочно обвързване на данни. Обикновено за малки приложения можете да използвате променлива за данни в същия компонент, но с нарастването на кода и изискванията може да има сценарии, при които ще трябва да използвате една и съща или множество променливи в различни компоненти в рамките на проекта.

Когато става въпрос за обвързване, има предимно три различни метода, които Angular предлага.

  • Свързване на свойства — -› []
  • Обвързване на събитие — -› ()
  • Двупосочно подвързване (комбинация от двете по-горе)— -› [()] — -› това се нарича още „Банан в кутията“

Нека се опитаме да ги разберем, като използваме пример, в който манипулираме променлива „accountBalance“. Ще използваме родителски и дъщерен компонент; от родителя можете да кредитирате сума с 10, а от детето можете да дебитирате същата.

Обвързване на свойства и обвързване на събития

Първо, нека дефинираме нашия родителски компонент.

// parent_component.component.ts
@Component({
  selector: 'parent_component',
  templateUrl: './parent_component.component.html',
  styleUrls: ['./parent_component.component.css']
})
export class ParentComponent implements OnInit {
    
    accountBalance : any;
    ngOnInit() {
       this.accountBalance = 500;
    }
    creditAccountBalance()
    {
        this.accountBalance += 10;
    }      
}

Тук accountBalance е променлива, декларирана вътре в родителския компонент, ние ще предадем тази променлива на дъщерния компонент в селекторите на компоненти.

// parent_component.component.html
<span> Balance Amount : {{accountBalance}} </span>
<button (click)=creditAccountBalance()> Add Amount </button>
<child_component [accountBalance]="accountBalance"> </child_component>

Ако променлива на компонент е предадена като Html атрибут (като този на последния ред), това е известно като свързване на свойства.

За да имаме angular да извиква някакъв код, когато се извършва действие/събитие, ние използваме обвързване за промяна на събитието. Класически пример за обвързване на събитие е click/change, което използвахме и в горния пример.

Сега нека дефинираме нашия дъщерен компонент с функция за дебитиране на салдото по сметката с 10. Дъщерният компонент може да слуша променливата, обвързана със свойството, като използва `@Input() декоратора`.

// child_component.component.ts
@Component({
  selector: 'child_component',
  templateUrl: './child_component.component.html',
  styleUrls: ['./child_component.component.css']
})
export class ChildComponent implements OnInit {
    @Input('accountBalance') accountBalance: any;
    debitAccountBalance()
    {
        this.accountBalance -= 10;
    }      
}
// child_component.component.html
<button (click)=debitAccountBalance()> Debit Amount </button>

Тук сумата ще бъде намалена с 10, но тъй като обвързването на свойства осигурява само еднопосочно обвързване, т.е. промяната, направена от родителския контролер, ще бъде разпозната в дъщерния контролер, но не и обратното. По този начин дебитираната стойност „accountBalance“ няма да бъде отразена в родителския компонент.

Двупосочно обвързване

За да разрешим проблема, който беше разгледан по-горе, ще трябва да използваме метода Банан в кутията. Но преди това нека разберем как можете да напишете персонализирани функции за свързване на събития. Първо, ще трябва да променим малко родителския Html.

// parent_component.component.html
<span> Balance Amount : {{accountBalance}} </span>
<button (click)=creditAccountBalance()> Add Amount </button>
<child_component [accountBalance]="accountBalance" (accountBalanceChange)="this.accountBalance= $event"> </child_component>

За да излъчим това събитие, ще трябва също да обвържем събитието вътре в дъщерния компонент, като използваме декоратора @OUTPUT.

// child_component.component.ts
@Component({
  selector: 'child_component',
  templateUrl: './child_component.component.html',
  styleUrls: ['./child_component.component.css']
})
export class ChildComponent implements OnInit {
    @Input('accountBalance') accountBalance: any;
    @Output() accountBalanceChange = new EventEmitter();
debitAccountBalance()
    {
        this.accountBalance -= 10;
        this.accountBalanceChange.emit(this.accountBalance);
    }      
}

С тази сума, дебитирана от дъщерния компонент, ще бъде призната и в родителския компонент. По-добър начин да напишете същото обвързване, но да използвате BANANA IN THE BOX [🍌], ​​би бил нещо подобно.

// parent_component.component.html
<span> Balance Amount : {{accountBalance}} </span>
<button (click)=creditAccountBalance()> Add Amount </button>
<child_component [accountBalance]="accountBalance" [(accountBalance)]="accountBalance"> </child_component>

Синтаксисът [()] е лесен за демонстриране, когато елементът има настройваемо свойство, наречено x, и съответното събитие, наречено xChange.

Bravvvoooooo... така постигате двупосочно свързване между компонентите. Освен това можете да добавите други дъщерни компоненти и промяната на стойността вътре в един ще бъде призната и сред другите дъщерни и родителски компоненти.

Надявам се, тази статия е била полезна!!