Passing HTML variables to Angular Component - javascript

I am trying to pass the items written in a text-box field on my webpage to variables in the component file. These variables will then be used in the service file that has a function link to the POST request I made on the python/SQLAlchemy side. I am using Flask with python/SQLAlchemy on the backend, and Angular CLI 7.0.5. Here's what I have:
<div class = "container">
<input id="InsertItemName" [(ngModel)]="InsertItemName"/>
<input id="InsertItemManu" [(ngModel)]="InsertItemManu"/>
<input id="InsertItemType" [(ngModel)]="InsertItemType"/>
<button (click)="sendValues()">Send</button>
</div>
modify-page.component.html:
import { Component, OnInit, Input } from '#angular/core';
import { ActivatedRoute, Data } from '#angular/router';
import { HttpResponse } from '#angular/common/http';
import { SelectItem } from 'primeng/components/common/selectitem';
import { MenuItem } from 'primeng/api';
import { ModifyService, ItemsData } from '../modify.service'
import { PARAMETERS } from '#angular/core/src/util/decorators';
#Component({
selector: 'app-modify-page',
templateUrl: './modify-page.component.html',
styleUrls: ['./modify-page.component.css']
})
export class ModifyPageComponent implements OnInit {
InsertItemName: string;
InsertItemManu: string;
InsertItemType: string;
insertItems: ItemsData;
constructor(
private modifyService: ModifyService,
private route: ActivatedRoute
) {
}
ngOnInit() {
this.insertItems.name = this.InsertItemName;
this.insertItems.manufacture = this.InsertItemManu;
this.insertItems.type = this.InsertItemType;
}
sendValues(): void {
console.log(this.InsertItemName, this.InsertItemManu, this.InsertItemType)
this.modifyService.postInputItems(this.insertItems)
}
}
modify.service.ts:
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
export interface ItemsData {
name: string;
manufacture: string;
type: string;
}
#Injectable({
providedIn: 'root'
})
export class ModifyService {
constructor(
public http: HttpClient
) { }
postInputItems(data: ItemsData){
return this.http.post('/modify/insertItems', data)
}
}
And if you need it, this is the database.py:
def insert_dbItems(a, b, c):
with engine.connect() as con:
ins = Items.insert().values(name = a, manufacture = b, type = c)
con.execute(ins)
return "Successfully inserted data into Items table"
and the init.py:
#app.route('/api/modify/insertItems', methods=["POST"])
def insert_Itemsdb():
body = json.loads(request.data)
a = body['name']
b = body['manufacture']
c = body['type']
return jsonify(database.insert_dbItems(a, b, c))
The database and init files work, I can use the Postman app and correctly insert the variables into my database from it. My problem is that when I run all the code above, I get left with this:
enter image description here
In conclusion: everything here is for me to take an input from a user and insert it into my database. Any help would be fantastic, thank you!

I think you forgot to initialize insertItems at the top of your ModifyPageComponent.
insertItems: ItemsData = {
name: null;
manufacture: null;
type: null;
}
Hope that will help!

Related

Retrieving the next item in an array by index in Angular 11

I have a list of employees in a JSON object in my service.ts file. It will be moved to a DB eventually. I know this is not the place for it. It's just for dev purposes. I am able to retrieve the employees by clicking on it and displaying them in a dynamic view component.
However, I want to be able to see the next employee on a button click without having to always go back to the main list. I am able to retrieve the index and increment the index on click. I just can't get the route to display the data for that index.
The HTML is pretty basic a simple button with a click method. The Service file looks like this:
import {HttpClient } from '#angular/common/http';
import { Injectable } from '#angular/core';
import { Employee } from '../models/employee.models';
#Injectable({
providedIn: 'root'
})
export class EmployeesService {
private listEmployees: Employee[] = [...regular json object...];
constructor() { }
getEmployees(): Employee[] {
return this.listEmployees;
}
getEmployee(id: number): Employee {
return this.listEmployees.find(e => e.id === id);
}
}
And my employee.component.ts file
import { ActivatedRoute } from '#angular/router';
import { EmployeesService } from './../../../services/employees.service';
import { Component, OnInit } from '#angular/core';
import { Employee } from 'src/app/models/employee.models';
import { Router } from '#angular/router';
#Component({
selector: 'employee',
templateUrl: './employee.component.html',
styleUrls: ['./employee.component.scss']
})
export class EmployeeComponent implements OnInit {
employee: Employee;
employees: Employee[];
index: number;
private _id: number;
constructor(
private _route: ActivatedRoute,
private _router: Router,
private _employeeService: EmployeesService
) { }
ngOnInit() {
this.employees = this._employeeService.getEmployees();
for ( this.index = 1; this.index < this.employees.length + 1; this.index++ ) {
this._route.paramMap.subscribe(params => {
this._id = +params.get('id')
console.log('this index:', this.index);
this.employee = this._employeeService.getEmployee(this._id);
});
}
}
viewNextEmployee() {
if( this.index < this.employees.length ){
this.index = this.index++;
console.log('this index:', this.index);
this._router.navigate(['/team', this._id])
} else {
this.index = 1;
}
}
}
I'm sorry, I can't really reproduce a working code. So many dependencies.

In Angular 9, how do I update a component's data field to show in the DOM without re-instantiating it?

I'm fairly new to Angular 9. I have a program where a user enters in a name - which, upon submitting - a POST HTTP request is sent and the name is stored. I then have an unrelated component for a sub-header that lists the names that have been stored using a GET HTTP request using ngOnInit(). However, I need the sub-header to update that list of names dynamically each time a new list is entered rather than just whenever the component instantiates.
I'm unsure how to proceed. I'm sure I could simply add a button that fetches and updates said list, but trying for something more dynamic. Thanks in advance!
//SERVICE.TS...
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { NewList } from './new-list.model';
import { map } from 'rxjs/operators';
#Injectable({
providedIn: 'root'
})
export class ListService {
createdLists: NewList[] = [];
constructor(private http: HttpClient) { }
createList(postData) {
return this.http
.post(
'API_KEY',
postData
);
}
getLists() {
return this.http
.get<NewList>(
'API_KEY'
).pipe(map(responseData => {
const responseArray: NewList[] = [];
for (const key in responseData) {
responseArray.push(responseData[key])
}
return responseArray;
})
);
}
}
// NEW-LIST-MENU.TS (USER ENTERS A NAME)...
import { Component, OnInit } from '#angular/core';
import { NgForm } from '#angular/forms';
import { Router } from '#angular/router';
import { ListService } from 'src/app/shared/list.service';
import { NewList } from 'src/app/shared/new-list.model';
import { UIService } from 'src/app/shared/ui.service';
#Component({
selector: 'app-new-list-menu',
templateUrl: './new-list-menu.component.html',
styleUrls: ['./new-list-menu.component.css']
})
export class NewListMenuComponent implements OnInit {
constructor(private listService: ListService,
private uiService: UIService,
private router: Router) { }
ngOnInit(): void {
}
onSubmit(form: NgForm) {
const listName = form.value.listname;
const newListObj = new NewList(listName, []);
this.listService.createList(newListObj)
.subscribe(() => {
this.router.navigate(['']);
});
const lists = this.listService.updateLists(newListObj);
form.reset();
}
onCancel() {
this.router.navigate(['']);
}
}
// SUB-HEADER.TS...
import { Component, OnInit, Output } from '#angular/core';
import { Router } from '#angular/router';
import { ListService } from 'src/app/shared/list.service';
import { NewList } from 'src/app/shared/new-list.model';
import { faWindowClose } from '#fortawesome/free-solid-svg-icons';
import { faPlusCircle } from '#fortawesome/free-solid-svg-icons';
import { faList } from '#fortawesome/free-solid-svg-icons';
import { faSignOutAlt } from '#fortawesome/free-solid-svg-icons';
import { Subject } from 'rxjs';
#Component({
selector: 'app-sub-header',
templateUrl: './sub-header.component.html',
styleUrls: ['./sub-header.component.css']
})
export class SubHeaderComponent implements OnInit {
createdLists: NewList[];
faWindowClose = faWindowClose;
faPlusCircle = faPlusCircle;
faList = faList;
faSignOutAlt = faSignOutAlt;
#Output() closeSub = new Subject();
constructor(private listService: ListService,
private router: Router) { }
ngOnInit(): void {
this.listService.getLists().subscribe((responseData) => {
this.createdLists = responseData;
});
}
onCloseSelect() {
this.closeSub.next();
}
onNewListSelect() {
this.onCloseSelect();
this.router.navigate(['new-list-menu']);
}
onLogOutSelect() {
}
}```
You can accomplish this in many ways, as these components are not related to each other, you can introduce a state service and use observables. see below possible solution
Create a new state service ListStateService
export class ListStateService {
private listData = new BehaviorSubject<NewList >({} as NewList);
listData$ = this.listData .asObservable();
}
Inject ListStateService into NewListMenuComponent
In the onSubmit, after you update,
const lists = this.listService.updateLists(newListObj);
this.listData .next(lists );
Inject ListStateService into SubHeaderComponent
In the ngOnInit(), subscribe to the ListStateService.listData$ and here you will get the value on changes
In your service, use an event emitter (very useful):
import { EventEmitter } from "#angular/core";
#Output() myEvent: EventEmitter<any> = new EventEmitter();
then emit new data to your sub header component through your service like so:
emitEvent (newData: Array<string>) {
this.myEvent.emit({
data: newData,
});
}
Subscribe to new data in your sub header component ngOnInit and use it:
this.myService.myEvent.subscribe((newData: Array<string>) => {
console.log(JSON.stringify(newData.data));
});
Note: Subscriptions will cause memory leaks if constantly re-subscribed in the component, so you can save the subscription and call unsubscribe() on it in the ngOnDestroy callback.
It's a little unclear what you are trying to do, but if you are trying to pass data from a parent component to a child component, you can do this either with Input fields or a ViewChild
to use Input fields your parent might looks like this:
<app-sub-header [names]="names"></app-sub-header>
then use an "Input" field in the child. Updating names in the parent should update the same named variable in the child in real time.

Property '' does not exist on type 'Object'

I was working all day in angular. Everything worked fine all day.
Restarted the server (ng serve). And now suddenly there are alot of errors.
I managed to fix most but I am stuck with this one.
This is the main part of the component .ts file:
import { Component, OnInit } from '#angular/core';
import { HttpService } from '../http.service';
#Component({
selector: 'app-playboard',
templateUrl: './playboard.component.html',
styleUrls: ['./playboard.component.scss']
})
export class PlayboardComponent implements OnInit {
brews: Object;
constructor(private _http: HttpService) { }
ngOnInit() {
this._http.myMethod().subscribe(data => {
this.brews = data;
this.dices = this.brews.myBox;
this.diceSeed = this.brews.boxID;
console.log(this.brews);
});
}
And this is the http.service.ts file:
import { Injectable } from '#angular/core';
import {HttpClient } from '#angular/common/http';
#Injectable({
providedIn: 'root'
})
export class HttpService {
constructor(private http: HttpClient) { }
myMethod() {
return this.http.get<Object>('https://localhost:44398/api/boggle');
}
myWordMethod(word) {
var url = 'https://localhost:44398/api/wordpoints/' + word;
return this.http.get<Object>(url);
}
}
It was working all day and suddenly these strange errors appear.
Does anyone have a clue of what could be wrong? Thanks alot!
Remove Object from your http calls. Using the generic is optional, especially if you haven't typed out your response.
import { Injectable } from '#angular/core';
import {HttpClient } from '#angular/common/http';
#Injectable({
providedIn: 'root'
})
export class HttpService {
constructor(private http: HttpClient) { }
myMethod() {
return this.http.get('https://localhost:44398/api/boggle');
}
myWordMethod(word) {
var url = 'https://localhost:44398/api/wordpoints/' + word;
return this.http.get(url);
}
}
On brews, declare it as any:
import { Component, OnInit } from '#angular/core';
import { HttpService } from '../http.service';
#Component({
selector: 'app-playboard',
templateUrl: './playboard.component.html',
styleUrls: ['./playboard.component.scss']
})
export class PlayboardComponent implements OnInit {
brews: any;
constructor(private _http: HttpService) { }
ngOnInit() {
this._http.myMethod().subscribe(data => {
this.brews = data;
this.dices = this.brews.myBox;
this.diceSeed = this.brews.boxID;
console.log(this.brews);
});
}
You can ignore these by simply delcaring them as the any type. For instance;
myWordMethod(word: any) {
..
}
this._http.myMethod().subscribe(data: any => {
..
});
That said declaring the actual type for TypeScript is often preferred. For Instance if your API sends back a common object with particular properties then declare it as such;
interface MyMethodResponse {
someProperty: string;
someNumber: number;
someArray: string[];
}
this._http.myMethod().subscribe((myMethodResponse: MyMethodResponse) => {
// TypeScript now knows that these properties exists on the response object
console.log(myMethodResponse.someArray);
console.log(myMethodResponse.someNumber);
console.log(myMethodResponse.someProperty);
});

Angular method returns undefined

As a beginner, I facing a problem with Angular and Observables. I have API for getting information about one specific restaurant in the database, but I have to get it with a POST request. I successfully get restaurantID from auth.service and another API when the restaurant is logged in, But when I tried to log restaurant in console, I get undefined. Uniformly I don't have permission to show API here. The code:
restaurant.service.ts
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { Restaurant } from '../models/Restaurant';
import { LoggedRestaurant } from '../models/LoggedRestaurant';
#Injectable({
providedIn: 'root'
})
export class RestaurantService {
private restaurantUrl = 'xxxxxxxxxxxx';
public restaurant: Restaurant;
public loggedRestaurant: LoggedRestaurant
public restaurantID;
constructor(private http: HttpClient) { }
public getRestaurant(): Observable<LoggedRestaurant> {
return this.http.post<LoggedRestaurant>(this.restaurantUrl, this.restaurantID);
}
}
informacije.component.ts
import { Component, OnInit } from '#angular/core';
import { AuthService } from '../services/auth.service';
import { RestaurantService } from '../services/restaurant.service';
import { Restaurant } from '../models/Restaurant';
import { LoggedRestaurant } from '../models/LoggedRestaurant';
import { Observable } from 'rxjs';
#Component({
selector: 'app-informacije',
templateUrl: './informacije.component.html',
styleUrls: ['./informacije.component.scss']
})
export class InformacijeComponent implements OnInit {
restaurant: Restaurant;
loggedRestaurant: LoggedRestaurant;
restaurantID;
constructor(private restaurantService: RestaurantService, private authService: AuthService ) { }
getRestaurant() {
return this.restaurantService.getRestaurant()
}
ngOnInit() {
this.restaurant = this.authService.currRestaurant[0];
console.log(this.restaurant)
console.log(this.loggedRestaurant)
this.restaurantID = this.restaurant.id;
console.log(this.restaurantID)
this.restaurantService.restaurantID =this.restaurantID;
}
}
httpClient.post() returns an observable (RXJS). So you need to subscribe to that. Otherwise, you may use the async pipe.
in your html, you can try this,
<span>{{getRestaurant() | aync}}</span>
OR,
you can declare a variable in your ts like data, and,
this.restaurantService.getRestaurant().subscribe(payload => {
this.data = payload;
})
and in your html, you can add,
<span *ngIf="data">{{data}}</span>
You need to subscribe to your API call.
In informacije.component.ts
getRestaurant() {
return this.restaurantService.getRestaurant()
.subscribe(data => this.restaurant = data);
}
This will asign the value returned by your service to your restaurant field in an asynchronous fashion.
In ngOnInit() call getRestaurant as follows
async ngOnInit() {
let restaurant = await this.getRestaurant().toPromise();
...
}

(Angular2) JSON data (http.get()) is undefined, and data is not updated in the component

My http-data.service accepts json for output in the component template. Initially, the console shows that the first few calls are given undefined, and the following calls are already taking json, but also if you check the component, then the component shows that the method that outputs the data to the component is called only once and since the data has not yet arrived it writes undefined , But not updated after the arrival of json. Help please understand why? Thank you
My http-data.service:
import {Injectable} from '#angular/core';
import {Http} from '#angular/http';
import {Response} from '#angular/http';
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operator/map';
#Injectable()
export class HttpService{
constructor(private http: Http) {}
getDataOrganizations(): Observable<any[]>{
return this.http.get('http://localhost:3010/data')
.map((resp:Response)=>{
let dataOrganizations = resp.json().organization;
return dataOrganizations;
});
}
getDataModules(): Observable<any[]> {
return this.http.get('http://localhost:3010/data')
.map((resp: Response)=> {
let dataModules = resp.json().modules;
return dataModules;
});
}
getDataPresets(): Observable<any[]> {
return this.http.get('http://localhost:3010/data')
.map((resp: Response)=> {
let dataPresets = resp.json().presets;
return dataPresets;
});
}
getDataModuleItems(): Observable<any[]> {
return this.http.get('http://localhost:3010/data')
.map((resp: Response)=> {
let dataModuleItems = resp.json().module_items;
return dataModuleItems;
});
}
}
My data-all.service
import { Injectable, EventEmitter } from '#angular/core';
import {Response} from '#angular/http';
import { ModuleModel } from './model-module';
import { ModuleItemsModel } from './model-module-items';
import data from '../data/data-all';
import { PriceService } from './price.service';
import { HttpService } from './http-data.service';
#Injectable()
export class ModuleDataService {
constructor(private priceService: PriceService, private httpService: HttpService){
this.dataMinMaxSum = {minSum: 0, maxSum: 0}
}
private currentPopupView: EventEmitter<any> = new EventEmitter<any>();
private dataModules: ModuleModel[] = this.getDataModules();
private dataMinMaxSum: {};
private dataCalculateVariationOrg: any[];
private dataChangeExecutor: any[];
subscribe(generatorOrNext?: any, error?: any, complete?: any) {
this.currentPopupView.subscribe(generatorOrNext, error, complete);
}
calculte(){
return this.priceService.getDataPrice();
}
getDataModules(){
this.httpService.getDataModules().subscribe(((modules)=>{this.dataModules = modules; console.log(this.dataModules);}));
console.log('dataModules');
console.log(this.dataModules);
return this.dataModules;
}
---------------------------------------------------------------------------
}
My left-block.component
import { Component, OnInit} from '#angular/core';
import { ModuleDataService } from '../../service/data-all.service';
import { ModuleModel } from '../../service/model-module';
#Component({
moduleId: module.id,
selector: 'modules-left-block',
templateUrl: './modules-left-block.html',
styleUrls: ['modules-left-block.css']
})
export class ModuleLeft implements OnInit{
modules: ModuleModel[];
constructor(private modulesAll: ModuleDataService){}
ngOnInit(){
this.modules = this.modulesAll.getDataModules();
console.log("view");
console.log(this.modulesAll.getDataModules());
}
onToggle(module: any){
this.modulesAll.toggleModules(module);
}
}
My left-block.component.html
<div class="modules-all">
<div class="modules-all-title">Все модули</div>
<div class="module-item" *ngFor="let module of modules" [ngClass]="{ 'active': module.completed }" (click)="onToggle(module)">{{module?.title}}</div>
</div>
In the component this.modulesAll.getDataModules () method is why it is executed only once without updating (write in console => undefined), if there are any thoughts, write, thanks.
This behaviour is due to the .subscribe() method does not wait for the data to arrive and I'm guessing you already know this. The problem you're facing is because, you have .subscribe to the getDataModules() service in the wron place. You shouldn't subscribe to a service in another service (at leat in this case). Move the subscribe method to the left-block.component and it should work.
getDataModules() {
this.httpService.getDataModules().subscribe(((modules) => {
this.dataModules = modules;
console.log(this.dataModules);
}));
console.log('dataModules');
console.log(this.dataModules);
return this.dataModules;
}
It should look somethig like this:
#Component({
moduleId: module.id,
selector: 'modules-left-block',
templateUrl: './modules-left-block.html',
styleUrls: ['modules-left-block.css']
})
export class ModuleLeft implements OnInit {
modules: ModuleModel[] = new ModuleModel();
constructor(private modulesAll: ModuleDataService, private httpService: HttpService) {}
ngOnInit() {
this.getDataModles();
//this.modules = this.modulesAll.getDataModules();
console.log("view");
//console.log(this.modulesAll.getDataModules());
}
onToggle(module: any) {
this.modulesAll.toggleModules(module);
}
getDataModules(): void {
this.httpService.getDataModules().subscribe(((modules) => {
this.modules = modules;
console.log(this.dataModules);
}));
}
}

Categories

Resources