ERROR TypeError: Cannot read property 'serviceId' of undefined - angularjs

Iam using nested json as input to Angular 6 where below is what my json structure looks like:
{"contractId":1,"contractName":"Temp","contractServiceList":[{"id":1,"serviceId":{"serviceId":1,"serviceName":"Emergency Room"},"providerTier":"Tier 1","coinsurance":100.0,"copay":10.0,"penaltyApplies":"Y","penaltyRule":"Non Emergency ER Use","penaltyType":"Dollar Amount","penaltyValue":300.0,"deductibleApplies":"Y"}]}
In component.ts, my code is:
export class AppComponent implements OnInit {
services: Service;
serviceId: ServiceId[];
contract: Contract[];
constructor(private formBuilder: FormBuilder, private router: Router, private contractService: ContractService) { }
addForm: FormGroup;
ngOnInit() {
this.serviceId = [
{serviceId: '1', serviceName: 'Emergency Room'},
{serviceId: '2', serviceName: 'OP Radiology'}
];
component.html :
<div class="form-group col-xs-6">
<label for="serviceName">Category Of Services:</label>
<select id ="serviceName" formControlName="serviceName" name="serviceName" class="form-control">
<option *ngFor="let serv of serviceId" [value]="serv.serviceId">{{serv.serviceName}}</option>
</select>
</div>
I am submitting all the values in the form as (ngSubmit)="onSubmit" and subscribing it as below:
onSubmit() {
this.contractService.saveContract(this.addForm.value)
.subscribe( data => {
alert('Contract created successfully');
});
}
Not sure why it's not able to take serviceId value. Any help is appreciable!!

Related

Finding ID from related model Laravel

I am working with three models:
User Model
class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array<int, string>
*/
protected $table = 'users';
protected $fillable = [
'name',
'email',
'password',
'group'
];
...
public function permission()
{
return $this->hasMany(Permission::class);
}
}
Profile Model
class Profile extends Model
{
use HasFactory;
protected $table = 'profiles';
protected $fillable = [
'profile_name',
'first_name',
'last_name',
'profile_type',
'TFN',
'ABN',
'ACN',
'Address',
'Email',
'Phone',
'established_date',
'Notes',
'activated'
];
...
public function permission()
{
return $this->hasMany(Permission::class);
}
}
Permission Model
class Permission extends Model
{
use HasFactory;
protected $table = 'permissions';
protected $fillable = [
'profile_id',
'user_id'
];
public function user()
{
return $this->belongsTo(User::class);
}
public function profile()
{
return $this->belongsTo(Profile::class);
}
}
Any user can have access to 0 or many profiles
Any profile can have permission given to 0 or many users
On the users.edit blade template I am creating toggle buttons to add/remove profile permissions for the selected user, using the permissions.store and permissions.destroy routes. Creating a new permission is working as expected, however I am having trouble accessing the permission id (marked **** in blade snippet) in order to trigger the destroy function.
User Controller
public function edit(User $user, Profile $profile, Permission $permission)
{
$perm = Permission::where([
['user_id', '=', $user->id],
])->pluck('profile_id', 'id')->toArray();
return view('users.edit', compact('perm'))
->with('user', $user)
->with('profiles', Profile::all());
}
Permission Controller
public function destroy(Permission $permission, User $user, Profile $profile)
{
$permission = Permission::where('user_id', '=', $user->id)
->where('profile_id', '=', $profile->id)
->firstOrFail();
$permission->delete();
return redirect()->back();
}
Blade snippet
#foreach($profiles as $key => $profile)
#if(in_array($profile->id, $perm))
<form action="{{ route('permissions.destroy', **** ) }}" method="POST" >
#csrf
#method('DELETE')
<input type="hidden" value="{{ $user->id }}" name="user_id" id="user_id" />
<input type="hidden" value="{{ $profile->id }}" name="profile_id" id="profile_id" />
<button class="btn btn-primary" type="submit">{{ $profile->profile_name }}</button>
</form>
#else
<form action="{{ route('permissions.store') }}" method="POST" >
#csrf
<input type="hidden" value="{{ $user->id }}" name="user_id" id="user_id" />
<input type="hidden" value="{{ $profile->id }}" name="profile_id" id="profile_id" />
<button class="btn btn-secondary" type="submit">{{ $profile->profile_name }}</button>
</form>
#endif
#endforeach
Thanks in advance
The permission ID is included in the array $perm created in the User controller, but I haven't found a way to call that value and associate it with the permission record so that I can send it to the permission.destroy route.
You can pass the permission ID as a parameter to the route in the action attribute of the form.
To do this, try replacing **** with ['permission' => array_search($profile->id, $perm)].
Here, the array_search() function is used to find the index of the profile ID in the $perm array, and the corresponding permission ID is accessed using that index. This value is then passed as a parameter named permission to the route in the form's action attribute.

Write out what i select in my <select> list in angular

I want to write out the option i choose from my select list. I know that i should use change but now how i should use it. !now im just writing to get the letters in!
My ts file:
import { Component, OnInit } from '#angular/core';
import { selectBeverage } from "../interface-beverage";
#Component({
selector: 'app-select-beverage',
templateUrl: './select-beverage.component.html',
styleUrls: ['./select-beverage.component.css']
})
export class SelectBeverageComponent implements OnInit {
beverages: selectBeverage[] = [
{ id: 1, drink: "Beer" },
{ id: 2, drink: "Soda" },
{ id: 3, drink: "Wine" },
{ id: 4, drink: "Water" }
];
clickedBeverage(){
}
constructor() {
}
ngOnInit(): void {
}
}
My template file:
<select [(ngModel)]="beverages">
<option *ngFor="let b of beverages" [value]="b.id">
{{b.drink}}
</option>
</select>
<br><br>
One {{selectedOption}}, coming right up! ```
Create a variable in the typescript file named beverageToDisplay and bind to that in the template within the <select> tag.
.ts
beverageToDisplay: string;
.html
<select [(ngModel)]="beverageToDisplay">
<option *ngFor="let b of beverages" >
{{b.drink}}
</option>
</select>
<p *ngIf="beverageToDisplay">One {{beverageToDisplay}}, coming right up!</p>
Working stackblitz found here.
The [(ngModel)] of the select contains the selected value, not the list of options.
.ts file:
export class SelectBeverageComponent implements OnInit {
...
// add member here
selectedOption: any; // instead of any one could use something more precise in the next step
...
}
Template file:
<select [(ngModel)]="selectedOption"> <!-- i corrected value of ngModel, it contains the selected value -->
<option *ngFor="let b of beverages" [value]="b.id">
{{b.drink}}
</option>
</select>
<br><br>
One {{selectedOption | json}}, coming right up! ```

NgFor only supports binding to Iterables such as Arrays while using array to create a dropdown selection

I am getting the below error while running the application:
ERROR Error: Cannot find a differ supporting object '[object Object]' of type 'subLandscape'. NgFor only supports binding to Iterables such as Arrays.
The subLandscape variable I am referring to in the HTML is an array but it throws an error while using it with "ngFor"
HTML:
<div class="form-group" [class.has-error]="subLandscape.invalid && subLandscape.touched">
<strong>Sub Landscape</strong>
<br>
<p>Please choose from one of the Sub Landscape options. Sub Landscape options are for reporting only.</p>
<label class="control-label">SubLandscape:</label>
<mat-select #subLandscape="ngModel" type="text" class="form-control" name="subLandscape" [ngModel]="model.subLandscape">
<mat-option *ngFor="let item of subLandscape">
{{ item }}
</mat-option>
</mat-select>
<div *ngIf="subLandscape.invalid && subLandscape.touched" class="alert alert-danger">
Select the Sub Landscape from the provided list.
</div>
</div>
Model:
export class SModel {
constructor (
public description: string,
public reasons: string,
public projectName: string,
public subLandscape: string,
public centerdata: string,
public nom: number,
public size: string,
public dbgh: string
) {
}
}
Component:
import { Component, OnInit } from '#angular/core';
import { Standalone } from '../standalone';
import { StandaloneModel } from '../models/standalone.model';
import {MatTableModule, MatTableDataSource} from '#angular/material/table';
#Component({
selector: 'app-standalone-form',
templateUrl: './standalone-form.component.html',
styleUrls: ['./standalone-form.component.css']
})
export class StandaloneFormComponent {
public project: string[] = ['', 'appdev', 'apptest', 'appqa'];
public subLandscape: string[] = ['DEV', 'Testing', 'QA', 'UAT'];
public dataCenter: string[] = ['PDC', 'SDC'];
public model = new SModel('', '', '', '', '', 0, '', '');
}
Probably because it is unable to differentiate between subLandscape from
#subLandscape="ngModel" and the component property array public subLandscape: string[] = ['DEV', 'Testing', 'QA', 'UAT'];. Change the name of either should solve the problem

Angular dynamic array showing all results not just data under id

I am still trying to learn what seems to me like advanced Angular 5. The below code does enter the "id" number from the array into the url as expected, but when I go to model/1 it shows my all the objects from the array. I need to only see the object under id 1 and same for each object in the array. I have found so much conflicting information online, from mapping to queries that I'm not even sure where to being and everything I've tried has led to no better results. I have included all the code I'm working with.
I have an array of objects in my json file-
[
{
"id": 1,
"label": "Metal Man",
"sample": "/assets/img/metalman1.png",
"fab": "https://sketchfab.com/models/1b3cb7f8a77145bc8616075e9036b025/embed",
"img1": "/assets/img/metalman1.png",
"img2": "/assets/img/metalman2.png",
"img3": "/assets/img/metalman3.png"
},
{
"id": 2,
"label": "Magrot",
"sample": "/assets/img/magrot1.png",
"fab": "https://sketchfab.com/models/e20c8ade2f16452ca7f440aa84fc8e33/embed",
"img1": "/assets/img/magrot1.png",
"img2": "/assets/img/magrot2.png",
"img3": "/assets/img/magrot3.png"
},
{
"id": 3,
"label": "Baseball and Bat",
"sample": "/assets/img/ball1.png",
"fab": "https://sketchfab.com/models/781c60d3449b46f996a081ae36c20cce/embed",
"img1": "/assets/img/ball1.png",
"img2": "/assets/img/ball2.png",
"img3": "/assets/img/ball3.png"
}
]
My template for each of the above objects-
<div class="columnFlex mainBlock" *ngFor="let model of modelwork">
<div class="modelImagery">
<h1>{{ model.label }}</h1>
<iframe [src]='sanitizer.bypassSecurityTrustResourceUrl(model.fab)'
frameborder="1" allowvr allowfullscreen mozallowfullscreen="true"
webkitallowfullscreen="true" onmousewheel=""></iframe>
<img [src]="model.img1" />
<img [src]="model.img2" />
<img [src]="model.img3" />
</div></div>
And my Activatedroute set up-
import { Component, OnInit } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { CommonModule } from '#angular/common';
import { DomSanitizer } from '#angular/platform-browser';
import { ActivatedRoute } from '#angular/router';
import { Router } from '#angular/router';
#Component({
selector: 'app-model',
templateUrl: './model.component.html',
styleUrls: ['./model.component.css']
})
export class ModelComponent implements OnInit {
modelwork: any;
constructor( private route: ActivatedRoute, private router: Router, private http: HttpClient, public sanitizer: DomSanitizer ) {
this.sanitizer = sanitizer;
this.route.params.subscribe(params => {this.modelwork = params['id'];});
}
ngOnInit(): void {
this.http.get<any>('./assets/models.json').subscribe(
data => {
this.modelwork = data;
})
}
}
Any clarification on what I'm needing to do would be so appreciated! I'm trying to learn Angular in days and it is more complicated than I had expected. Thank you for taking the time to look at this!
I don't see anything advanced here. You simple have two asynchronous operations that both set the variable 'modelwork'. One of the operations sets modelwork to an integer and the other sets it to a json array. depending on which operation resolves first.
Edit
Looking at your comment, i see what you want to do. Here's an example:
chosenIndex: any;
modelwork: any;
constructor( private route: ActivatedRoute, private router: Router, private http: HttpClient, public sanitizer: DomSanitizer ) {
this.sanitizer = sanitizer;
}
ngOnInit(): void {
this.route.params.subscribe(params => {
this.chosenIndex = params['id'];
this.http.get<any>('./assets/models.json').subscribe(data => {
this.modelwork = data.filter(d => d['id'] == this.chosenIndex);
})
});
}
Modelwork will now contain an array of 1 object. The one object you want. You can alter this example to get whatever output you want.

Angular 2 RC4 - Select ngModel delayed update

I'm trying to create a select control that will bind the value to an Object and on change I can get access to the selected object.
I know there has a been a lot of changes in the forms so not sure if this is a user error or bug or not possible.
Here is where I'm at so far: Link to Plunker
import { Component } from '#angular/core';
#Component({
selector: 'my-app',
template: `
<h1>My First Angular 2 App</h1>
<select (change)="onChange($event)" [(ngModel)]="selected">
<option value=''></option>
<option *ngFor="let d of data" [ngValue]="d">
{{d.name}}
</option>
</select>
`
})
export class AppComponent {
diagnostic;
selected;
data = [
{ id: 1 , name: 'query 1', filters: [
{ 'filter1': 'material = 1'},
{'filter2': 'plant = 2'}
]
},
{ id: 2 , name: 'query 2', filters: [
{ 'filter1': 'material = 1'},
{'filter2': 'plant = 2'}
]
}
];
onChange(event) {
console.log(event.target.value);
console.log(this.selected);
}
}
What I would like to have happen is that when the onChange event is called that either I pass the Object value of the selected item into that method or get access to the selected value through the property bound in ngModel.
//expected
onChange(event) {
console.log(event.target.value) // selected object bound to ngValue
console.log(this.selected) // ngModel updated to object bound to selected option
}
But unfortunately, the event.target.value is a string version of the object and this.selected sort of works but is always behind on being updated.
Is there another way or proper way to handle this? Is the delay in the ngModel a bug?
Any help would be appreciated!
You should define select inputs/outputs as following:
<select [(ngModel)]="selected" (ngModelChange)="onChange()">
<option *ngFor="let d of data" [ngValue]="d">
{{d.name}}
</option>
</select>
and then the model is correctly applied to the property. http://plnkr.co/edit/JGgflTY9LvrDDhqqlSGP?p=preview
Notice that the definition of ngModel and ngModelChange should be ordered as is in example :)

Resources