0
   <tr *ngFor="let row of categories ">
    <td>{{row.categoryName}}</td>

    <td>{{row.visible}}</td>
    <td>{{row.instanceNumber}}</td>
    <td> <a class="btn btn-info btn-fill " [routerLink]="['/control/category']">Modify</a>
    </td>

Here i want to send the row/category object along with the routing, but i'm redirected to an empty form! i want to map the current row data to the original form so that i can modify only some fields not all.

I use formbuilder in angular!

ngOnInit() {
    this.relationForm = this.fb.group({
      relationName: ['', [Validators.required, Validators.minLength(3), Validators.pattern('[a-z]+([A-Z][a-z]*)*')  ]],
      humanFormat: ['', [Validators.required, Validators.minLength(3)]],
      populate: ['', [Validators.required, Validators.pattern('TRUE|FALSE')]],
      visible: ['', [Validators.required, Validators.pattern('TRUE|FALSE')]],
      generalizations: ['', [Validators.required, Validators.minLength(3),Validators.pattern('[a-z]+([A-Z][a-z]*)*') ]],

I know i have to use something like this but where and how is the question!

 this.productForm.patchValue({
            productName: this.product.productName,
            productCode: this.product.productCode,
            starRating: this.product.starRating,
            description: this.product.description
        });
        this.productForm.setControl('tags', this.fb.array(this.product.tags || []));
Raghavendra S S
  • 115
  • 3
  • 12

1 Answers1

1

Here is a simplified example of your code. Where you iterate your data, have a click event where you pass the chosen item, something like this:

<div *ngFor="let relation of relations">
 {{relation.categoryName}} 
 <button (click)="modify(relation)">Modify</button>
</div>

Then in your click event let's store the chosen item in a service before navigating so that we can then fetch it after navigation:

modify(relation) {
  this.service.addRelation(relation);
  this.router.navigate(['your path here'])
}

With the above, we also need to inject Router in the constructor to be able to use it: private router: Router.

I'm not going to entirely explain the service, there is a detailed description in the official docs about this. The point is to use an observable, in this case we need something else than a Subject as Subject requires next() to emit values, whereas BehaviorSubject will always emit if there is a subscriber, more here in this Answer.

Service:

private relation = new BehaviorSubject<Object>({})

relation$ = this.relation.asObservable()

addRelation(relation) {
  this.relation.next(relation)
}

Then in your other component, where you have the form, subscribe to the observable in the service, and then build your form based on the values you get:

constructor(private service: RelationService, private fb: FormBuilder) {
  service.relation$.subscribe(relation => {
    this.relation = relation;
    this.buildForm();
  });
}

And then you just fill the values in your form with the object you have received:

buildForm() {
  this.relationForm = this.fb.group({
    categoryName: [this.relation.categoryName],
    author: [this.relation.author]
  });
}

So this is a simplified example that you can work with and adapt to your own code!

Finally, here's a DEMO to play with.

AT82
  • 71,416
  • 24
  • 140
  • 167
  • Whoa! Thanks again ;) you have such an amazing command over Angular :D I will try this and let you know but if you see my example I have a seperate component where create the category form! I'm still trying to understand how this will fit in :) – Raghavendra S S Jul 22 '17 at 06:15
  • No problem :) Separate component? Well, this is a separate component in plunker as well (`detail`), maybe I'm misunderstanding here when you talk about separate component? :D But if you encounter problems, create a [MCVE](https://stackoverflow.com/help/mcve) meaning a **working** plunker with so little code as possible that showcases your issue then I'm happy to take a look :) – AT82 Jul 22 '17 at 07:31
  • relation$ = this.relation.asObservable() why a $ at the end of relation? 1 place i'm hitting the issue is when i try to access export class DetailComponent { relation = {}; relationForm: FormGroup; buildForm() { this.relationForm = this.fb.group({ categoryName: [this.relation.categoryName], author: [this.relation.author] }) } I'm unable to access this.realtion.categoryName because i guess we have declared it empty in the Detail component. relation={} I'm unable to set categoryName in the formBuilder fucntion! – Raghavendra S S Jul 22 '17 at 07:33
  • the `$` is just a naming convention, to separate between `relation` and the **observable** `relation$`. The problem shouldn't be that relation is empty, since we build the form **after** we have set values to relation inside the subscription. Or this depends entirely, is detail component a child component? If so, then this issue would appear. – AT82 Jul 22 '17 at 07:43
  • buildForm() { this.relationForm = this.fb.group({ //Here I'm unable to acess this.realtion.category categoryName: [this.relation.categoryName], author: [this.relation.author] }) } That's the only thing that's not happening in my code except everything is working as you suggested. I get "Property categoryName doesn't exist on type '{}' " as error message. – Raghavendra S S Jul 22 '17 at 07:54
  • Yes I understand, but I can't tell, since the code in the plunker in my answer works well with that setup, so there must be some other issue, and we cannot figure that one out unless we have something to debug. That piece of code is correct, so something else is the issue ;) – AT82 Jul 22 '17 at 07:59
  • should i use something like this ? @ViewChildren(FormControlName, { read: ElementRef }) formInputElements: ElementRef[]; i was so relaxed looking at your code that it's finally can be done :D then got stuck in accessing a property :( – Raghavendra S S Jul 22 '17 at 08:02
  • Cool i will add all the code in plunker including app.route.ts :) – Raghavendra S S Jul 22 '17 at 08:08
  • Yeah you're totally right ! Category is the children of Control ! so that's why i'm not able to access it ? http://plnkr.co/edit/WlnTHrAR6NBux4zbQ9kP?p=preview Here is the routes.ts rest of the code is the same but this changes everything right? – Raghavendra S S Jul 22 '17 at 08:14
  • so the problem is if in your code detail component is the children of another component, how will you handle this.realtion.cateoryName in buildForm() method ! – Raghavendra S S Jul 22 '17 at 08:19
  • Okay, so you still doesn't have a working plunker.... :( So I'm forced to guess.... If it is a child which is present when parent is, the first subscription the object will be empty, so you need to set an if condition to check if the object is empty. But if this a child tag, you can also just then use a `Subject` instead. I don't know, I am just guessing here. If this is not the issue, I cannot help further unless you provide a **working** plunker, I am sorry. – AT82 Jul 22 '17 at 08:19
  • I'm new to plunker not sure how to make it working ! :( I will try my best to comeup with a code in your setup ! { path: 'control', component: UserComponent, children:[{path: 'category', component: NellOntologyCategoryComponent}, { path: 'relation', component:NellOntologyRelationComponent}] } So category is a child ! that's why i'm unable to access categoryName. – Raghavendra S S Jul 22 '17 at 08:23
  • Yes you can use the one I created in this answer, it has the routing and everything set, so it's just to replace the code I have with yours. You do not need to add any more components or lots of code. Just the **minimal** needed to reproduce the issue, and as mentioned... A working plunker ;) – AT82 Jul 22 '17 at 08:25
  • Yup did it ! if i make detail a children it doesn't work ! ;) modify button in your list component doesn't work.http://plnkr.co/edit/t0qqPdLtWRdFGV6OHt2W?p=preview updated the plunker ! – Raghavendra S S Jul 22 '17 at 08:32
  • You have not stated how the child is rendered, is it router-outlet or child tag in parent? I can't keep guessing, you need to help me help you! – AT82 Jul 22 '17 at 08:37
  • sorry i updated that in the router modify(relation) { this.service.addRelation(relation); this.router.navigate(['/list/detail']) } Yeah i'm really not doing well here i totally accept it :( – Raghavendra S S Jul 22 '17 at 08:37
  • I have a new issue with setInterval in angular i want to call a function every 5 secs. import { IntervalObservable } from 'rxjs/observable/IntervalObservable'; @Component({ ... }) export class AppComponent { n: number = 0; constructor() { IntervalObservable.create(1000).subscribe(n => this.n = n); } } Will something like this work? – Raghavendra S S Jul 23 '17 at 09:50
  • I suggest you open a new question for whatever problems you might have :) – AT82 Jul 23 '17 at 09:52
  • https://stackoverflow.com/questions/45263894/angular-2-implement-rxjs-observable-intervalobservable-for-http-call-for-every-a here you go :D – Raghavendra S S Jul 23 '17 at 10:12
  • I have a novice level understanding of how map() works but in your example getRelations(): Observable { return this.http.get('src/data.json').map(this.extractData) } private extractData(response: Response){ let body = response.json(); // console.log("Body :####", body); return body || []; } Why we need extractData? we could simply do map( res => res.json()) right? if we use map on array it does what ever the function we pass inside map() on each element of the array but in your code how can it be visualized ? – Raghavendra S S Jul 26 '17 at 06:47
  • Sorry I don't really understand your (latter) question... But no, we don't need `extractData` at all, it's just like any other generic helper method, you can use `map` totally fine instead of `extractData` – AT82 Jul 26 '17 at 06:50
  • i updated my comment, so even if i do map( response => response.json()) that's also fine? I'm not able to understand how it's assigning an interface variables but just writing a single line of code :P – Raghavendra S S Jul 26 '17 at 06:51
  • That is perfectly fine! And that is how I do it myself! :) – AT82 Jul 26 '17 at 06:52
  • var numbers = [1, 4, 9]; var roots = numbers.map(Math.sqrt); // roots is now [1, 2, 3] // numbers is still [1, 4, 9] I understand this, but I'm not able to understand how http.get('data.json').map( res => res.json()) to the interface variables :( it's like in Java we have setters and getters , or constructors perhaps to do the job but here i don't see a thing in map( res=> res.json() ) :P – Raghavendra S S Jul 26 '17 at 06:55
  • Hi :) need your help, BehaviorSubject next method is not working throwing not a function error. :( https://stackoverflow.com/questions/46452347/behaviorsubject-gives-error-for-next-function-when-i-try-to-add-the-variable-usi Could you please help me ? – Raghavendra S S Sep 27 '17 at 16:47