How to send array object input to firestore on Angular? - arrays

I'm just learning angular and trying to make a to-do-list app. I'm trying to send array object data to firestore. I have an array object input like this:
[
{
"isChecked": true
"title": "Todo 1",
},
{
"isChecked": true,
"title": "Todo 2"
}
]
I want to enter that into the input field. And here is my input field:
<form action="" #importForm="ngForm (ngSubmit)="importJson(importForm, $event)">
<div class="form-group">
<textarea ngModel name="importjson" #importjson="ngModel" class="form-control" id="exampleFormControlTextarea1" rows="10" required></textarea>
</div>
<button type="submit" class="btn btn-secondary" >Ok</button>
</form>
And this is my app component :
import { Component, ViewChild, OnInit, ElementRef } from '#angular/core';
import { FormsModule } from '#angular/forms';
import { FormGroup } from '#angular/forms';
import { TodolistService } from '../../services/todolist.service';
import { Todolist } from '../../model/todolist.model';
export class TodolistComponent implements OnInit {
importjson: Todolist={};
constructor(private todolistService: TodolistService) { }
#ViewChild('editTitle', {static: false}) input: ElementRef;
ngOnInit(): void{
this.todolistService.getToDoList().subscribe(items => {
this.todos = items;
})
}
importJson(importForm: FormGroup, submit){
console.log(importForm.value.importjson);
this.todolistService.addImport(importForm.value.importjson);
this.importState = false;
}
}
And here is my app service:
import { Injectable } from '#angular/core';
import { AngularFireDatabase, AngularFireList } from '#angular/fire/database' ;
import { AngularFirestore, AngularFirestoreCollection, AngularFirestoreDocument } from '#angular/fire/firestore';
import { Observable } from 'rxjs';
import { Todolist } from '../model/todolist.model';
#Injectable({
providedIn: 'root'
})
export class TodolistService {
itemsCollection: AngularFirestoreCollection<Todolist>;
items: Observable<Todolist[]>;
itemDoc: AngularFirestoreDocument<Todolist>;
constructor(private firebasedb: AngularFireDatabase, public firestore: AngularFirestore) {
this.itemsCollection = this.firestore.collection('titles');
this.items = this.itemsCollection.snapshotChanges().pipe(
map(actions => actions.map(a => {
const data = a.payload.doc.data() as Todolist;
data.id = a.payload.doc.id;
return data;
}))
);
}
addImport(item: Todolist) {
this.itemsCollection.add(item);
}
How can I do that?

Related

Material angular autocomplete keeps giving me error

I am trying to make this demo work but somehow it is not working for me. It keeps giving me error
servers.component.ts
import { Component } from '#angular/core';
import {FormControl} from '#angular/forms';
import {Observable} from 'rxjs/Observable';
import {startWith} from 'rxjs/operators/startWith';
import {map} from 'rxjs/operators/map';
#Component({
selector: 'app-servers',
templateUrl: './servers.component.html',
styleUrls: ['./servers.component.css']
})
export class User {
constructor(public name: string) { }
}
export class ServersComponent {
myControl = new FormControl();
options = [
new User('Mary'),
new User('Shelley'),
new User('Igor')
];
filteredOptions: Observable<User[]>;
ngOnInit() {
this.filteredOptions = this.myControl.valueChanges
.pipe(
startWith<string | User>(''),
map(value => typeof value === 'string' ? value : value.name),
map(name => name ? this.filter(name) : this.options.slice())
);
}
filter(name: string): User[] {
return this.options.filter(option =>
option.name.toLowerCase().indexOf(name.toLowerCase()) === 0);
}
displayFn(user?: User): string | undefined {
return user ? user.name : undefined;
}
}
I have imported both User class and ServersComponent in app.module.ts.
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { AlertModule } from 'ngx-bootstrap';
import "hammerjs";
import { BrowserAnimationsModule } from '#angular/platform-browser/animations';
import {MatButtonModule, MatInputModule } from '#angular/material';
import { FormsModule, ReactiveFormsModule } from '#angular/forms';
import { AppComponent } from './app.component';
import { ServerComponent } from './server/server.component';
import { ServersComponent, User } from './servers/servers.component';
import { MyFormComponent } from './my-form/my-form.component';
import {MatCheckboxModule} from '#angular/material/checkbox';
import {MatAutocompleteModule} from '#angular/material/autocomplete';
#NgModule({
declarations: [
AppComponent,
ServerComponent,
ServersComponent,
MyFormComponent,
User,
],
imports: [
BrowserModule,
BrowserAnimationsModule,
AlertModule.forRoot(),
FormsModule,
ReactiveFormsModule,
MatButtonModule,
MatInputModule,
MatCheckboxModule,
MatAutocompleteModule,
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
However if i use this demo it is working fine.
Can you let me know what I am doing wrong in my code.
Problem lies in this line,
import { ServersComponent, User } from './servers/servers.component';
Usually you can have only one component from a select/component. Remove User from the same.
To add more on the issue, you should not export two classes from same component. change your component as,
import { Component } from '#angular/core';
import {FormControl} from '#angular/forms';
import {Observable} from 'rxjs/Observable';
import {startWith} from 'rxjs/operators/startWith';
import {map} from 'rxjs/operators/map';
#Component({
selector: 'app-servers',
templateUrl: './servers.component.html',
styleUrls: ['./servers.component.css']
})
export class ServersComponent {
myControl = new FormControl();
options = [
new User('Mary'),
new User('Shelley'),
new User('Igor')
];
filteredOptions: Observable<User[]>;
ngOnInit() {
this.filteredOptions = this.myControl.valueChanges
.pipe(
startWith<string | User>(''),
map(value => typeof value === 'string' ? value : value.name),
map(name => name ? this.filter(name) : this.options.slice())
);
}
filter(name: string): User[] {
return this.options.filter(option =>
option.name.toLowerCase().indexOf(name.toLowerCase()) === 0);
}
displayFn(user?: User): string | undefined {
return user ? user.name : undefined;
}
}

Redux not passing state to container

I'm having a problem receiving the state on my ActiveMessage object from my reducers. When I click an object on the message list, I can see that it flows through the action, through the correct reducer, but doesn't arrive on the local props for ActiveMessage. I'm not sure why it's not receiving the state on active_message prop. Can anyone point me in the right direction as to why this isnt working?
message_list.js
import React, {Component} from 'react';
import {connect} from 'react-redux';
import MessageStub from "./message_stub";
import {activateMessage} from "../../actions/index";
import {bindActionCreators} from 'redux';
class MessageList extends Component {
constructor(props) {
super(props);
this.state = {
selected_message: null
};
this.selectMessage = this.selectMessage.bind(this);
}
selectMessage(event, index, message){
this.setState({selected_message: index});
this.props.activateMessage(message);
}
renderMessageList() {
return this.props.message_list.map((message, index) =>
<tr key={index}>
<td className={index === this.state.selected_message ? "message-stub-body active-message-stub" : "message-stub-body"}
onClick={(e) => this.selectMessage(e, index, message)}>
<MessageStub />
</td>
<td>
{index === this.state.selected_message && <div className="message-stub-arrow"/>}
</td>
</tr>
);
}
render() {
return (
<div className="message-list">
<table className="message-list-table">
<tbody>
{this.renderMessageList()}
</tbody>
</table>
</div>
);
}
}
function mapStateToProps(state){
return {
message_list: state.message_list,
};
}
function mapDispatchToProps(dispatch){
return bindActionCreators({activateMessage: activateMessage}, dispatch)
}
export default connect(mapStateToProps, mapDispatchToProps)(MessageList);
active_message.js
import React, {Component} from 'react';
import {connect} from 'react-redux';
import MessageOut from "./message_out";
import MessageIn from "./message_in";
class ActiveMessage extends Component {
constructor(props) {
super(props);
this.scrollToBottom = this.scrollToBottom.bind(this);
}
componentDidMount() {
this.scrollToBottom();
}
componentDidUpdate() {
this.scrollToBottom();
}
scrollToBottom() {
this.el.scrollTop = this.el.scrollHeight;
}
renderMessages(){
return this.props.active_message.messages.map((message, i) =>
<MessageOut key={i} onClick={() => {
this.scrollToBottom
}}/>
);
}
render() {
console.log("rendering");
console.log(this.props.active_message);
if(!this.props.active_message){
return <div>loading...</div>
}
return (
<div className="active-message-div">
<div className="active-message"
ref={el => {
this.el = el;
}}>
{this.renderMessages()}
</div>
<div className="message-reply-div">
<textarea className="message-reply-input" placeholder="Type a message..."/>
</div>
</div>
);
}
}
function mapStateToProps(state){
console.log("mapping");
return{
active_message: state.active_message
}
}
export default connect(mapStateToProps)(ActiveMessage);
actions/index.js
export const ACTIVATE_MESSAGE = 'activate_message';
export function activateMessage(message){
console.log("calling action " + message)
return{
type: ACTIVATE_MESSAGE,
payload: message
};
}
reducers/index.js
import { combineReducers } from 'redux';
import MessageListReducer from './reducer_message_list';
import ActiveMessageReducer from './reducer_active_message';
const rootReducer = combineReducers({
message_list: MessageListReducer,
active_message: ActiveMessageReducer,
});
export default rootReducer;
reducer_active_message.js
import {ACTIVATE_MESSAGE} from "../actions/index";
export default function(state = null, action){
switch(action.type){
case ACTIVATE_MESSAGE:
console.log("reducing through ACTIVE_MESSAGE");
return action.payload;
}
return state;
}
reducer_message_list.js
export default function(){
return[
{
user: {
first_name: "First",
last_name: "Last",
type: "P"
},
messages: [
{
message: "hi",
inbound: true
},
{
message: "bye",
inbound: false
}
]
},
{
user: {
first_name: "First2",
last_name: "Last2",
type: "O"
},
messages: [
{
message: "hi",
inbound: true
},
{
message: "bye",
inbound: false
}
]
}
];
}
I have loaded this into CodeSandbox. I'm able to get this to work.
https://codesandbox.io/s/7y9nlvvprq
NOTE: Your reducer_message_list is not a reducer, just a static data set.

Ag-Grid require delete button for each row

I am trying to implement a solution with ag-grid and not got stuck into a problem. I am trying to implement edit and delete button in each row .edit button implementation is successful but problem is with delete button. I have tried best of my knowledge (which is little for angular 2) .Please see the implementation as per below code:-
court.component.ts
import { Component } from '#angular/core';
import { Court } from './court.model';
//import './../utils/array.extensions';
import { GridOptions } from "ag-grid";
import { DataCourtService } from '../services/data-court.service';
import { EditButtonComponent } from "../utils/editbutton.component";
#Component({
selector: 'court',
template: require('./court.component.html'),
providers: [DataCourtService]
})
export class CourtComponent {
private gridOptions: GridOptions;
public courts : Court[];
onQuickFilterChanged(event: any) {
this.gridOptions.api.setQuickFilter(event.target.value);
}
constructor() {
var courtservice = new DataCourtService();
this.gridOptions = {
rowSelection: 'single'
};
// this.gridOptions.angularCompileRows = true;
this.gridOptions.columnDefs = [
{
headerName: "Court Name",
field: "courtname",
editable: true
} ,
{
headerName: "Action",
cellRendererFramework: EditButtonComponent,
colId: "edit"
}
];
this.gridOptions.rowData = courtservice.getCourt();
}
}
EditButton.component.ts
import {Component} from "#angular/core";
import {ICellRendererAngularComp} from "ag-grid-angular/main";
#Component({
selector: 'edit-button',
template: `<button (click)="invokeEditMethod()" class="btn btn-primary btn-xs"><span class="glyphicon glyphicon-edit"></span>Edit</button>
<button (click)="invokeDeleteMethod()" class="btn btn-danger btn-xs"><span class="glyphicon glyphicon-remove"></span>Delete</button>`
})
export class EditButtonComponent implements ICellRendererAngularComp {
public params: any;
agInit(params: any): void {
this.params = params;
}
public invokeDeleteMethod() {
var selectedData = this.params.api.getSelectedRows();
this.params.api.updateRowsData({remove: selectedData});
alert("hi");
}
public invokeEditMethod() {
this.params.api.setFocusedCell(this.params.node.rowIndex, 'courtname');
this.params.api.startEditingCell({
rowIndex: this.params.node.rowIndex,
colKey: 'courtname',
}
);
}
}
In this function
public invokeDeleteMethod() {
var selectedData = this.params.api.getSelectedRows();
this.params.api.updateRowsData({remove: selectedData});
alert("hi");
}
I am recieving an error as UpdateRowData is not an function. Can you please help me to achieve this??
This function was introduced in aggrid 10+ and I am using 8+.updating it resolved the issue.
The real problem with that code is that
this.params.api.updateRowsData({remove: selectedData});
Expects an array in version 22.X.X
this.params.api.updateRowsData({remove: [selectedData]});

Angular displaying correct array item in buttons

I have an array with 4 items, and 4 buttons on a dashboard. I want to assign item1 with button1, and item2 with button2 etc. Right now it displays 4 buttons for each "hero" for a total of 16 buttons. I tried {{hero.name[2]}} and similar things but that just grabs letters and not the actual array items. I would appreciate any help.
dashboard.component.html
<h3>Calibrations</h3>
<div class="grid grid-pad">
<a *ngFor="let hero of heroes" [routerLink]="['/detail', hero.id]">
<button style ="min-height: 70px" (click)="gotoClick(1)">{{hero.name}}</button>
<button style ="min-height: 70px" (click)="gotoClick(2)">{{hero.name}}</button>
<button style ="min-height: 70px" (click)="gotoClick(3)">{{hero.name}}</button>
<button style ="min-height: 70px" (click)="gotoClick(4)">{{hero.name}}</button>
</a>
</div>
dashboard.component.ts
import { Component, OnInit } from '#angular/core';
import { Hero } from '../hero.class';
import { HeroService } from '../hero.service';
import { StepService } from '../step.service';
#Component({
moduleId: module.id,
selector: 'app-dashboard',
templateUrl: './dashboard.component.html',
styleUrls: ['./dashboard.component.css']
})
export class DashboardComponent implements OnInit {
heroes: Hero[] = [];
constructor(private heroService: HeroService, private _stepService: StepService, private _teststepService: StepService) { }
ngOnInit() {
this.heroService.getHeroes().subscribe(heroes => this.heroes = heroes);
}
private test: number;
gotoClick(value: number){
this._stepService.setTest(value);
this._teststepService.apiURL();
}
}
hero.service.ts
import { Injectable } from '#angular/core';
import { Headers, Http, Response } from '#angular/http';
import { Hero } from './hero.class';
import { Observable } from "rxjs/Rx";
#Injectable()
export class HeroService {
private headers = new Headers({'Content-Type': 'application/json'});
private heroesUrl = 'api/heroes'; // URL to web api
constructor(private http: Http){ }
getHeroes(): Observable<Hero[]> {
return this.http.get(this.heroesUrl)
.map(response => response.json().data as Hero[]);
}
getHero(id: number): Observable<Hero> {
const url = `${this.heroesUrl}/${id}`;
return this.http.get(url)
.map(response => response.json().data as Hero);
}
}
You can use the built-in index property of *ngFor:
<div class="grid grid-pad">
<a *ngFor="let hero of heroes; let i = index;" [routerLink]="['/detail', hero.id]">
<button style ="min-height: 70px" (click)="gotoClick(i)">{{hero?.name}</button>
</a>
</div>
Documentation: https://angular.io/docs/ts/latest/api/common/index/NgFor-directive.html

while retrieving passed array got from json in the second component,i am getting [object Object]

This is the first component where i am pushing those things into array named items and i am trying to get it in the second component through service
import { Component } from '#angular/core';
import { FormBuilder, FormControl } from '#angular/forms';
import {AppService} from '../second/app.service';
import { Router } from '#angular/router';
import { Http,Response } from '#angular/http';
import { routing, appRoutingProviders } from '../app.route';
import { Validators } from '#angular/forms';
import {BrowserModule} from '#angular/platform-browser';
#Component({
selector: 'first-app',
templateUrl:"../app/src/component/first/app.firstpage.html"
})
export class FirstComponent
{
data:any;
public items=[];
public edited=false;
public city=false;
public dateCon=false;
inputForm: FormGroup;
Select: FormControl;
Selectt: FormControl;
dat:FormControl;
constructor(private appservice:AppService,builder: FormBuilder, router:Router)
{
this.appservice.getData().subscribe(res=>{this.data=res.json()});
console.log(this.data);
this.Select = new FormControl('', [
Validators.required
]);
this.Selectt = new FormControl('', [
Validators.required
]);
this.dat = new FormControl('', [
Validators.required
]);
this.inputForm = builder.group({
Select: this.Select,
Selectt: this.Selectt,
dat: this.dat
});
this.router=router;
this.appservice=appservice;
}
ngOnInit(){
this.appservice.getData()
}
onclick(a,b) {
console.log(this.data);
let sel1=this.inputForm.value.Select;
let sel2=this.inputForm.value.Selectt;
let sel3=this.inputForm.value.dat;
console.log(sel3);
console.log(sel1);
console.log(sel2);
console.log(this.data.bus.length);
for(let i=0;i<this.data.bus.length;i++){
if((this.data.bus[i].from==sel1)&&(this.data.bus[i].to==sel2))
{
this.items.push(this.data.bus[i]);
}
}
this.appservice.setData(this.items);
}
if((sel1!="")&&(sel2!="")&&(sel3!="")&&(sel1!=sel2))
{
this.router.navigate(['/sec-component']);
}
else if((sel1=="")&&(sel2=="")&&(sel3==""))
{
this.edited=true;
}
if((sel1==sel2)&&((sel1!="")&&(sel2!="")))
{
this.edited=false;
this.city=true;
}
else
{
this.city=false;
}
if(sel1!=sel2)
{
this.edited=false;
}
if(sel3=="")
{
this.dateCon=true;
}
else
{
this.dateCon=false;
}
}
}
This is the second component to which i am passing this array and i need to get that printed over there and each properties to be accessed rather than the entire stuff.
import { Component } from '#angular/core';
import {AppService} from '../first/first.service';
#Component({
template:
`
<h1>second component</h1>
<h1>second component</h1>
<p >{{myName}}</p>
`
})
export class SecondComponent {
constructor(private appservice: AppService)
{
this.appservice=appservice;
this.myName=appservice.getVal();
}
}
This is the service page where i am returning the values
import {Component, Injectable,Input,Output,EventEmitter} from '#angular/core'
import { Http, Response } from '#angular/http';
export interface myData
{
name:any;
}
#Injectable()
export class AppService
{
sharingData: myData={name:""};
constructor(private http:Http){ }
getData()
{
return this.http.get('./app/src/component/busDet.json')
}
setData(i)
{
console.log('save data function called' + i + this.sharingData.name);
this.sharingData.name=i;
console.log(this.sharingData.name);
}
getVal()
{
console.log(this.sharingData.name);
return this.sharingData.name;
}
}
I am getting the output as object.object
I am not able to get the values with in the JSON in the next component.

Resources