Angular 6+. How to extend a template adding new actions such as JSF?
up vote
0
down vote
favorite
I'm trying to implement the concept of pages composition from JSF in Angular6 + but I have no idea how to start it. Here is what I need:
1) A template page such as search page where there are placeholders for fields, search action and search results table.
2) A page that extends template and add its fields, action and results
3) Possibility to extend # 2 and add custom actions to results data table rows.
Following picture describes each item above:
1) Search page general template
2) Custom search page (extends #1)
3) Custom action added to search page (extends #2)
3.1) Similar page to #3 but it has different action on result row (extends #2)
I want to is to standardize all the pages based on few base templates (# 1) and reuse specific pages adding new actions to it (#2). As the result, # 3 will be shown the final user and it may be used in different places with minor changes, for instance, I can search for the employee and open it OR I can lookup employee using this same search page but instead of opening its record, I will select it to fill a field from other form. In this example, all I need to do is the extend #2 and add specific action that will open or just lookup employee and set to other form.
PS: Developer may add component in placeholders.
Updates:
22/11/2018
Based on advice from Bunyamin Coskuner, I implemented a sample pretty quickly but now I'm stuck on a specific behavior.
I created a StackBlitz project and published my sample code:
https://stackblitz.com/edit/angular-s2wkpw
Just click on "search" and take a look at the results. Action buttons are added only in last row. What is the best way to replicate these buttons in every row?
PS: Each button must pass correct parameter based on what is in the row to controller.
I would like to ask the Angular experts if is this the best approach to archieve what I'm trying to.
Thanks in advance.
angular
add a comment |
up vote
0
down vote
favorite
I'm trying to implement the concept of pages composition from JSF in Angular6 + but I have no idea how to start it. Here is what I need:
1) A template page such as search page where there are placeholders for fields, search action and search results table.
2) A page that extends template and add its fields, action and results
3) Possibility to extend # 2 and add custom actions to results data table rows.
Following picture describes each item above:
1) Search page general template
2) Custom search page (extends #1)
3) Custom action added to search page (extends #2)
3.1) Similar page to #3 but it has different action on result row (extends #2)
I want to is to standardize all the pages based on few base templates (# 1) and reuse specific pages adding new actions to it (#2). As the result, # 3 will be shown the final user and it may be used in different places with minor changes, for instance, I can search for the employee and open it OR I can lookup employee using this same search page but instead of opening its record, I will select it to fill a field from other form. In this example, all I need to do is the extend #2 and add specific action that will open or just lookup employee and set to other form.
PS: Developer may add component in placeholders.
Updates:
22/11/2018
Based on advice from Bunyamin Coskuner, I implemented a sample pretty quickly but now I'm stuck on a specific behavior.
I created a StackBlitz project and published my sample code:
https://stackblitz.com/edit/angular-s2wkpw
Just click on "search" and take a look at the results. Action buttons are added only in last row. What is the best way to replicate these buttons in every row?
PS: Each button must pass correct parameter based on what is in the row to controller.
I would like to ask the Angular experts if is this the best approach to archieve what I'm trying to.
Thanks in advance.
angular
This is totally doable, but to answer it will take some time which is I don't have right now. I would suggest you to read about angular content projection and try to come up with a solution. If you try to implement it yourself and ask some questions along the way, people will more likely try to help you. At this moment, you haven't provided any code that you've written.
– Bunyamin Coskuner
Nov 19 at 13:13
Hello @BunyaminCoskuner! Thank you for your time, actually I'm looking for a starting point and you gave me one, I'll find more info about content projection and try to implement and share some code here.
– Emilio Numazaki
Nov 19 at 13:43
Hello @BunyaminCoskuner, added a sample code but now I'm stuck on specific issue. Could you, please, advice me what is the best way to solve it?
– Emilio Numazaki
2 days ago
Alright, I'll check it out and get back to you.
– Bunyamin Coskuner
2 days ago
Posted an answer
– Bunyamin Coskuner
2 days ago
add a comment |
up vote
0
down vote
favorite
up vote
0
down vote
favorite
I'm trying to implement the concept of pages composition from JSF in Angular6 + but I have no idea how to start it. Here is what I need:
1) A template page such as search page where there are placeholders for fields, search action and search results table.
2) A page that extends template and add its fields, action and results
3) Possibility to extend # 2 and add custom actions to results data table rows.
Following picture describes each item above:
1) Search page general template
2) Custom search page (extends #1)
3) Custom action added to search page (extends #2)
3.1) Similar page to #3 but it has different action on result row (extends #2)
I want to is to standardize all the pages based on few base templates (# 1) and reuse specific pages adding new actions to it (#2). As the result, # 3 will be shown the final user and it may be used in different places with minor changes, for instance, I can search for the employee and open it OR I can lookup employee using this same search page but instead of opening its record, I will select it to fill a field from other form. In this example, all I need to do is the extend #2 and add specific action that will open or just lookup employee and set to other form.
PS: Developer may add component in placeholders.
Updates:
22/11/2018
Based on advice from Bunyamin Coskuner, I implemented a sample pretty quickly but now I'm stuck on a specific behavior.
I created a StackBlitz project and published my sample code:
https://stackblitz.com/edit/angular-s2wkpw
Just click on "search" and take a look at the results. Action buttons are added only in last row. What is the best way to replicate these buttons in every row?
PS: Each button must pass correct parameter based on what is in the row to controller.
I would like to ask the Angular experts if is this the best approach to archieve what I'm trying to.
Thanks in advance.
angular
I'm trying to implement the concept of pages composition from JSF in Angular6 + but I have no idea how to start it. Here is what I need:
1) A template page such as search page where there are placeholders for fields, search action and search results table.
2) A page that extends template and add its fields, action and results
3) Possibility to extend # 2 and add custom actions to results data table rows.
Following picture describes each item above:
1) Search page general template
2) Custom search page (extends #1)
3) Custom action added to search page (extends #2)
3.1) Similar page to #3 but it has different action on result row (extends #2)
I want to is to standardize all the pages based on few base templates (# 1) and reuse specific pages adding new actions to it (#2). As the result, # 3 will be shown the final user and it may be used in different places with minor changes, for instance, I can search for the employee and open it OR I can lookup employee using this same search page but instead of opening its record, I will select it to fill a field from other form. In this example, all I need to do is the extend #2 and add specific action that will open or just lookup employee and set to other form.
PS: Developer may add component in placeholders.
Updates:
22/11/2018
Based on advice from Bunyamin Coskuner, I implemented a sample pretty quickly but now I'm stuck on a specific behavior.
I created a StackBlitz project and published my sample code:
https://stackblitz.com/edit/angular-s2wkpw
Just click on "search" and take a look at the results. Action buttons are added only in last row. What is the best way to replicate these buttons in every row?
PS: Each button must pass correct parameter based on what is in the row to controller.
I would like to ask the Angular experts if is this the best approach to archieve what I'm trying to.
Thanks in advance.
angular
angular
edited 2 days ago
asked Nov 19 at 12:54
Emilio Numazaki
346
346
This is totally doable, but to answer it will take some time which is I don't have right now. I would suggest you to read about angular content projection and try to come up with a solution. If you try to implement it yourself and ask some questions along the way, people will more likely try to help you. At this moment, you haven't provided any code that you've written.
– Bunyamin Coskuner
Nov 19 at 13:13
Hello @BunyaminCoskuner! Thank you for your time, actually I'm looking for a starting point and you gave me one, I'll find more info about content projection and try to implement and share some code here.
– Emilio Numazaki
Nov 19 at 13:43
Hello @BunyaminCoskuner, added a sample code but now I'm stuck on specific issue. Could you, please, advice me what is the best way to solve it?
– Emilio Numazaki
2 days ago
Alright, I'll check it out and get back to you.
– Bunyamin Coskuner
2 days ago
Posted an answer
– Bunyamin Coskuner
2 days ago
add a comment |
This is totally doable, but to answer it will take some time which is I don't have right now. I would suggest you to read about angular content projection and try to come up with a solution. If you try to implement it yourself and ask some questions along the way, people will more likely try to help you. At this moment, you haven't provided any code that you've written.
– Bunyamin Coskuner
Nov 19 at 13:13
Hello @BunyaminCoskuner! Thank you for your time, actually I'm looking for a starting point and you gave me one, I'll find more info about content projection and try to implement and share some code here.
– Emilio Numazaki
Nov 19 at 13:43
Hello @BunyaminCoskuner, added a sample code but now I'm stuck on specific issue. Could you, please, advice me what is the best way to solve it?
– Emilio Numazaki
2 days ago
Alright, I'll check it out and get back to you.
– Bunyamin Coskuner
2 days ago
Posted an answer
– Bunyamin Coskuner
2 days ago
This is totally doable, but to answer it will take some time which is I don't have right now. I would suggest you to read about angular content projection and try to come up with a solution. If you try to implement it yourself and ask some questions along the way, people will more likely try to help you. At this moment, you haven't provided any code that you've written.
– Bunyamin Coskuner
Nov 19 at 13:13
This is totally doable, but to answer it will take some time which is I don't have right now. I would suggest you to read about angular content projection and try to come up with a solution. If you try to implement it yourself and ask some questions along the way, people will more likely try to help you. At this moment, you haven't provided any code that you've written.
– Bunyamin Coskuner
Nov 19 at 13:13
Hello @BunyaminCoskuner! Thank you for your time, actually I'm looking for a starting point and you gave me one, I'll find more info about content projection and try to implement and share some code here.
– Emilio Numazaki
Nov 19 at 13:43
Hello @BunyaminCoskuner! Thank you for your time, actually I'm looking for a starting point and you gave me one, I'll find more info about content projection and try to implement and share some code here.
– Emilio Numazaki
Nov 19 at 13:43
Hello @BunyaminCoskuner, added a sample code but now I'm stuck on specific issue. Could you, please, advice me what is the best way to solve it?
– Emilio Numazaki
2 days ago
Hello @BunyaminCoskuner, added a sample code but now I'm stuck on specific issue. Could you, please, advice me what is the best way to solve it?
– Emilio Numazaki
2 days ago
Alright, I'll check it out and get back to you.
– Bunyamin Coskuner
2 days ago
Alright, I'll check it out and get back to you.
– Bunyamin Coskuner
2 days ago
Posted an answer
– Bunyamin Coskuner
2 days ago
Posted an answer
– Bunyamin Coskuner
2 days ago
add a comment |
1 Answer
1
active
oldest
votes
up vote
0
down vote
You came pretty close, I just added a directive to solve the rest. Here is the final stackblitz
<ng-content select="...>
works on static content projection. Sometimes, you need more powerful directive than that.
There is a little trick I got it from Angular Material codebase and use it in almost all of my components which is providing customizable templates.
Instead of writing <ng-content select="button">
which overrides other rows of the table and only put the button
s on the last one, you declare a directive as follows
@Directive({ selector: '[appPersonSearchButtons]' })
export class TemplatePersonSearchButtonsDirective {
constructor(public template: TemplateRef<any>) { }
}
This directive may not look like it is doing much and I assure you it is!
It has single property which is template
. It is injected here because we will use this directive with ng-template
only! If you use this directive on any other element than ng-template
you will get an error!
You should put this directive into declarations
array of your module
declarations: [ ... TemplatePersonSearchButtonsDirective ... ]
Now, it is time to change <ng-content select="button">
to something else.
First, let's make sure whether consumers of this component used this directive within their template.
I added this line to TemplatePersonSearchComponent
@ContentChild(TemplatePersonSearchButtonsDirective) buttons: TemplatePersonSearchButtonsDirective;
I've changed <tr *ngFor...>
to following
<tr *ngFor="let person of persons; let i = index">
<td width="80%">{{person}}</td>
<td>
<ng-container *ngIf="buttons">
<ng-container *ngTemplateOutlet="buttons.template;
context: { $implicit: person, index: i}">
</ng-container>
</ng-container>
</td>
</tr>
ngTemplateOutlet
is a directive that takes a TemplateRef
as an input (which comes from buttons.template
in this case). Also, you can pass a context too so that you can expose some data to the users (which will come in handy later).
Let's use it in our employee-search-component
. It is pretty much the same as you wrote it, I just moved button
s inside of an ng-template
as follows
<app-template-person-search>
<ng-template appPersonSearchButtons let-personObj let-id="index">
<button (click)="openPerson(personObj, id)">Open</button>
<button (click)="deletePerson(personObj, id)">Delete</button>
</ng-template>
</app-template-person-search>
Remember, we defined our context as context: { $implicit: person, index: i}"
Since, we defined person
as $implicit
, you can write anything starting with let-
to retrieve that object. I chose personObj
to show that you can type anything. Also, I retrieved index
as id
and pass these objects into a function.
openPerson(person, id) {
alert('Open ' + person + ' ' + id);
}
deletePerson(person, id) {
alert('Delete ' + person + ' ' + id);
}
add a comment |
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
0
down vote
You came pretty close, I just added a directive to solve the rest. Here is the final stackblitz
<ng-content select="...>
works on static content projection. Sometimes, you need more powerful directive than that.
There is a little trick I got it from Angular Material codebase and use it in almost all of my components which is providing customizable templates.
Instead of writing <ng-content select="button">
which overrides other rows of the table and only put the button
s on the last one, you declare a directive as follows
@Directive({ selector: '[appPersonSearchButtons]' })
export class TemplatePersonSearchButtonsDirective {
constructor(public template: TemplateRef<any>) { }
}
This directive may not look like it is doing much and I assure you it is!
It has single property which is template
. It is injected here because we will use this directive with ng-template
only! If you use this directive on any other element than ng-template
you will get an error!
You should put this directive into declarations
array of your module
declarations: [ ... TemplatePersonSearchButtonsDirective ... ]
Now, it is time to change <ng-content select="button">
to something else.
First, let's make sure whether consumers of this component used this directive within their template.
I added this line to TemplatePersonSearchComponent
@ContentChild(TemplatePersonSearchButtonsDirective) buttons: TemplatePersonSearchButtonsDirective;
I've changed <tr *ngFor...>
to following
<tr *ngFor="let person of persons; let i = index">
<td width="80%">{{person}}</td>
<td>
<ng-container *ngIf="buttons">
<ng-container *ngTemplateOutlet="buttons.template;
context: { $implicit: person, index: i}">
</ng-container>
</ng-container>
</td>
</tr>
ngTemplateOutlet
is a directive that takes a TemplateRef
as an input (which comes from buttons.template
in this case). Also, you can pass a context too so that you can expose some data to the users (which will come in handy later).
Let's use it in our employee-search-component
. It is pretty much the same as you wrote it, I just moved button
s inside of an ng-template
as follows
<app-template-person-search>
<ng-template appPersonSearchButtons let-personObj let-id="index">
<button (click)="openPerson(personObj, id)">Open</button>
<button (click)="deletePerson(personObj, id)">Delete</button>
</ng-template>
</app-template-person-search>
Remember, we defined our context as context: { $implicit: person, index: i}"
Since, we defined person
as $implicit
, you can write anything starting with let-
to retrieve that object. I chose personObj
to show that you can type anything. Also, I retrieved index
as id
and pass these objects into a function.
openPerson(person, id) {
alert('Open ' + person + ' ' + id);
}
deletePerson(person, id) {
alert('Delete ' + person + ' ' + id);
}
add a comment |
up vote
0
down vote
You came pretty close, I just added a directive to solve the rest. Here is the final stackblitz
<ng-content select="...>
works on static content projection. Sometimes, you need more powerful directive than that.
There is a little trick I got it from Angular Material codebase and use it in almost all of my components which is providing customizable templates.
Instead of writing <ng-content select="button">
which overrides other rows of the table and only put the button
s on the last one, you declare a directive as follows
@Directive({ selector: '[appPersonSearchButtons]' })
export class TemplatePersonSearchButtonsDirective {
constructor(public template: TemplateRef<any>) { }
}
This directive may not look like it is doing much and I assure you it is!
It has single property which is template
. It is injected here because we will use this directive with ng-template
only! If you use this directive on any other element than ng-template
you will get an error!
You should put this directive into declarations
array of your module
declarations: [ ... TemplatePersonSearchButtonsDirective ... ]
Now, it is time to change <ng-content select="button">
to something else.
First, let's make sure whether consumers of this component used this directive within their template.
I added this line to TemplatePersonSearchComponent
@ContentChild(TemplatePersonSearchButtonsDirective) buttons: TemplatePersonSearchButtonsDirective;
I've changed <tr *ngFor...>
to following
<tr *ngFor="let person of persons; let i = index">
<td width="80%">{{person}}</td>
<td>
<ng-container *ngIf="buttons">
<ng-container *ngTemplateOutlet="buttons.template;
context: { $implicit: person, index: i}">
</ng-container>
</ng-container>
</td>
</tr>
ngTemplateOutlet
is a directive that takes a TemplateRef
as an input (which comes from buttons.template
in this case). Also, you can pass a context too so that you can expose some data to the users (which will come in handy later).
Let's use it in our employee-search-component
. It is pretty much the same as you wrote it, I just moved button
s inside of an ng-template
as follows
<app-template-person-search>
<ng-template appPersonSearchButtons let-personObj let-id="index">
<button (click)="openPerson(personObj, id)">Open</button>
<button (click)="deletePerson(personObj, id)">Delete</button>
</ng-template>
</app-template-person-search>
Remember, we defined our context as context: { $implicit: person, index: i}"
Since, we defined person
as $implicit
, you can write anything starting with let-
to retrieve that object. I chose personObj
to show that you can type anything. Also, I retrieved index
as id
and pass these objects into a function.
openPerson(person, id) {
alert('Open ' + person + ' ' + id);
}
deletePerson(person, id) {
alert('Delete ' + person + ' ' + id);
}
add a comment |
up vote
0
down vote
up vote
0
down vote
You came pretty close, I just added a directive to solve the rest. Here is the final stackblitz
<ng-content select="...>
works on static content projection. Sometimes, you need more powerful directive than that.
There is a little trick I got it from Angular Material codebase and use it in almost all of my components which is providing customizable templates.
Instead of writing <ng-content select="button">
which overrides other rows of the table and only put the button
s on the last one, you declare a directive as follows
@Directive({ selector: '[appPersonSearchButtons]' })
export class TemplatePersonSearchButtonsDirective {
constructor(public template: TemplateRef<any>) { }
}
This directive may not look like it is doing much and I assure you it is!
It has single property which is template
. It is injected here because we will use this directive with ng-template
only! If you use this directive on any other element than ng-template
you will get an error!
You should put this directive into declarations
array of your module
declarations: [ ... TemplatePersonSearchButtonsDirective ... ]
Now, it is time to change <ng-content select="button">
to something else.
First, let's make sure whether consumers of this component used this directive within their template.
I added this line to TemplatePersonSearchComponent
@ContentChild(TemplatePersonSearchButtonsDirective) buttons: TemplatePersonSearchButtonsDirective;
I've changed <tr *ngFor...>
to following
<tr *ngFor="let person of persons; let i = index">
<td width="80%">{{person}}</td>
<td>
<ng-container *ngIf="buttons">
<ng-container *ngTemplateOutlet="buttons.template;
context: { $implicit: person, index: i}">
</ng-container>
</ng-container>
</td>
</tr>
ngTemplateOutlet
is a directive that takes a TemplateRef
as an input (which comes from buttons.template
in this case). Also, you can pass a context too so that you can expose some data to the users (which will come in handy later).
Let's use it in our employee-search-component
. It is pretty much the same as you wrote it, I just moved button
s inside of an ng-template
as follows
<app-template-person-search>
<ng-template appPersonSearchButtons let-personObj let-id="index">
<button (click)="openPerson(personObj, id)">Open</button>
<button (click)="deletePerson(personObj, id)">Delete</button>
</ng-template>
</app-template-person-search>
Remember, we defined our context as context: { $implicit: person, index: i}"
Since, we defined person
as $implicit
, you can write anything starting with let-
to retrieve that object. I chose personObj
to show that you can type anything. Also, I retrieved index
as id
and pass these objects into a function.
openPerson(person, id) {
alert('Open ' + person + ' ' + id);
}
deletePerson(person, id) {
alert('Delete ' + person + ' ' + id);
}
You came pretty close, I just added a directive to solve the rest. Here is the final stackblitz
<ng-content select="...>
works on static content projection. Sometimes, you need more powerful directive than that.
There is a little trick I got it from Angular Material codebase and use it in almost all of my components which is providing customizable templates.
Instead of writing <ng-content select="button">
which overrides other rows of the table and only put the button
s on the last one, you declare a directive as follows
@Directive({ selector: '[appPersonSearchButtons]' })
export class TemplatePersonSearchButtonsDirective {
constructor(public template: TemplateRef<any>) { }
}
This directive may not look like it is doing much and I assure you it is!
It has single property which is template
. It is injected here because we will use this directive with ng-template
only! If you use this directive on any other element than ng-template
you will get an error!
You should put this directive into declarations
array of your module
declarations: [ ... TemplatePersonSearchButtonsDirective ... ]
Now, it is time to change <ng-content select="button">
to something else.
First, let's make sure whether consumers of this component used this directive within their template.
I added this line to TemplatePersonSearchComponent
@ContentChild(TemplatePersonSearchButtonsDirective) buttons: TemplatePersonSearchButtonsDirective;
I've changed <tr *ngFor...>
to following
<tr *ngFor="let person of persons; let i = index">
<td width="80%">{{person}}</td>
<td>
<ng-container *ngIf="buttons">
<ng-container *ngTemplateOutlet="buttons.template;
context: { $implicit: person, index: i}">
</ng-container>
</ng-container>
</td>
</tr>
ngTemplateOutlet
is a directive that takes a TemplateRef
as an input (which comes from buttons.template
in this case). Also, you can pass a context too so that you can expose some data to the users (which will come in handy later).
Let's use it in our employee-search-component
. It is pretty much the same as you wrote it, I just moved button
s inside of an ng-template
as follows
<app-template-person-search>
<ng-template appPersonSearchButtons let-personObj let-id="index">
<button (click)="openPerson(personObj, id)">Open</button>
<button (click)="deletePerson(personObj, id)">Delete</button>
</ng-template>
</app-template-person-search>
Remember, we defined our context as context: { $implicit: person, index: i}"
Since, we defined person
as $implicit
, you can write anything starting with let-
to retrieve that object. I chose personObj
to show that you can type anything. Also, I retrieved index
as id
and pass these objects into a function.
openPerson(person, id) {
alert('Open ' + person + ' ' + id);
}
deletePerson(person, id) {
alert('Delete ' + person + ' ' + id);
}
edited 2 days ago
answered 2 days ago
Bunyamin Coskuner
3,1041530
3,1041530
add a comment |
add a comment |
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53375104%2fangular-6-how-to-extend-a-template-adding-new-actions-such-as-jsf%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
This is totally doable, but to answer it will take some time which is I don't have right now. I would suggest you to read about angular content projection and try to come up with a solution. If you try to implement it yourself and ask some questions along the way, people will more likely try to help you. At this moment, you haven't provided any code that you've written.
– Bunyamin Coskuner
Nov 19 at 13:13
Hello @BunyaminCoskuner! Thank you for your time, actually I'm looking for a starting point and you gave me one, I'll find more info about content projection and try to implement and share some code here.
– Emilio Numazaki
Nov 19 at 13:43
Hello @BunyaminCoskuner, added a sample code but now I'm stuck on specific issue. Could you, please, advice me what is the best way to solve it?
– Emilio Numazaki
2 days ago
Alright, I'll check it out and get back to you.
– Bunyamin Coskuner
2 days ago
Posted an answer
– Bunyamin Coskuner
2 days ago