How to create a button to add an object? - javascript

I am trying to make a raffle project. I'm stuck at the step where I have to create a button on click that will add the first name in a table of absentees.
I created my mock in which I declared my values ​​(names etc.) then I imported my array into my component. I have my HTML in which there is my <select> and ` tag which allows to create a list. I would like a button that allows you to add an absentee to a list
<div>
<h1>Ajouter un.e absent.e </h1>
<select>
<option value="placeholder">Séléctionner une personne</option>
<option value="liste des étudiants" *ngFor="let option of students">
{{option.name}}
</option>
</select>
<button (click)="add()">Ajouter une personne</button>
import { Component } from '#angular/core';
import { Students, STUDENTS } from 'src/app/mock/students';
#Component({
selector: 'app-absents',
templateUrl: './absents.component.html',
styleUrls: ['./absents.component.css'],
})
export class AbsentsComponent {
students : Students[] = STUDENTS;
absents = [];
add() {
????
}

Related

how to make the data of the "data" function reverberate in the graph?

i have a graph that i want to use two files with the points of it. I would like to know how I can change between the two files with a selector. I made the following code but the graph doesn't change after selecting. I believe the "date" data is overwritten but not reflected in the chart. What can I do?
<template>
<div class="home">
<select #change="onChange($event)">
<option value="dataFile1">file one</option>
<option value="dataFile2">file two</option>
</select>
<LineGraph2 :vul_data="data"/>
</div>
</template>
<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator';
import LineGraph2 from '#/components/LineGraph2.vue';
import {data1} from '#/data/file1.js'
import {data2} from '#/data/file2.js'
#Component({
components: {
LineGraph2,
},
})
export default class HomeView extends Vue {
data() {
return {
data: data1,
}
}
onChange(event: any) {
if(event.target != null){
this.data = data2 as any
}
}
}
</script>
If you use chart.js you need to call the update function on your chart after you change the data but i don't see how you pass the new data to the component (i didn't use Vue before so i am just asking to check if you passed new data correctly)

Pass two values from dropdowns to service in angular

I need to pass two values from two different dropdowns to my service. And I would like to do it on click on the button. So I wrote component like this:
import { Component, Input, OnInit } from '#angular/core';
import { CategoryType } from '../models/category-type.enum';
import { CountryType } from '../models/country-type.enum';
import { NewsServiceService } from '../services/news-service.service';
#Component({
selector: 'app-dropdown',
template:
`
<div>
<select [(ngModel)]="catSelected" (ngModelChange) = "onClick($event)" >
<option *ngFor = "let type of CategoryType.values()" [ngValue] = 'type'>
{{type}}
</option>
</select>
<br>
<select [(ngModel)]="couSelected" (ngModelChange) = "onClick($event)" >
<option *ngFor = "let type of CountryType.values()" [ngValue] = 'type'>
{{type}}
</option>
</select>
<br>
<button ng-click="onClick()">Click to get news</button>
</div>
`
})
export class DropdownComponent implements OnInit {
CategoryType = CategoryType;
CountryType = CountryType;
title: string;
couSelected: string;
catSelected: string;
constructor(private newsService: NewsServiceService) {
}
ngOnInit() {
this.catSelected = 'Select_Category';
this.couSelected = 'Select_Country';
}
onClick(catSelected: string, couSelected: string) {
this.newsService.getNews(catSelected, couSelected).subscribe(
data => {
this.catSelected = data;
}
);
}
}
Like i wrote I have two dropdowns with values
CategoryType
CountryType
and one button to submit the click.
Every change on dropdown makes ngModelChange and send only one value to my services.
I wanna achive:
Select value from CategoryType
Select value from CountryType
Then Click the button and pass values CategoryType and CountryType to my service.
Right now only one value is passed and I dont know why.
onClick function does not working at all.
Becouse your are passing only one value to onClick() function.
Correct by passing the elements from inside of DropdownComponent instead of passing it as click($event)
import { Component, Input, OnInit } from '#angular/core';
import { CategoryType } from '../models/category-type.enum';
import { CountryType } from '../models/country-type.enum';
import { NewsServiceService } from '../services/news-service.service';
#Component({
selector: 'app-dropdown',
template:
`
<div>
<select [(ngModel)]="catSelected" >
<option *ngFor = "let type of CategoryType.values()" [ngValue] = 'type'>
{{type}}
</option>
</select>
<br>
<select [(ngModel)]="couSelected">
<option *ngFor = "let type of CountryType.values()" [ngValue] = 'type'>
{{type}}
</option>
</select>
<br>
<button ng-click="onClick()">Click to get news</button>
</div>
`
})
export class DropdownComponent implements OnInit {
CategoryType = CategoryType;
CountryType = CountryType;
title: string;
couSelected: string;
catSelected: string;
constructor(private newsService: NewsServiceService) {
}
ngOnInit() {
this.catSelected = 'Select_Category';
this.couSelected = 'Select_Country';
}
onClick() {
this.newsService.getNews(this.catSelected, this.couSelected).subscribe(
data => {
this.catSelected = data;
}
);
}
}
There are two main problems with your code:
You're getting catSelected and couSelected from parameters, but you could use simply this reference:
onClick() {
this.newsService.getNews(this.catSelected, this.couSelected)...
}
You're using ng-click instead of (click), that's why button's click isn't being fired. Do this:
<button (click)="onClick()">Click to get news</button>
That being said, I want to give you some tips:
Don't call functions in templates. Instead, declare CategoryType and CountryType like this:
readonly categoryTypes = CategoryType.values();
readonly countryTypes = CountryType.values();
Don't use [ngValue] for primitive types. It isn't necessary. You can just use [value].

Angular 4/5 Component variable from Subject/Services not binding to HTML template

I have a variable in my app.component.ts file that is passed in from a controller via my services.ts file.
As far as I can see, the Object property passed to the Component via the Subject is working, because I can console.log(this.selectedContact.name) and It will log to the console perfectly, which would mean that it is correctly being stored into the variable selectedContact: any;. But I cannot seem to bind this to my HTML and I am curious as to what I may be missing.
Here is my app.component.ts file for the view I'm attempting to bind to:
import { Component, OnInit } from '#angular/core';
import { ContactsListComponent } from '../contacts-list/contacts-list.component';
import { ApiService } from '../api.service';
#Component({
selector: 'app-contact-details',
templateUrl: './contact-details.component.html',
styleUrls: ['./contact-details.component.scss']
})
export class ContactDetailsComponent implements OnInit {
selectedContact: any;
constructor(private _apiService: ApiService) { }
ngOnInit() { this.showContact()}
showContact() {
this._apiService.newContactSubject.subscribe(
contact => {
this.selectedContact = contact;
console.log(this.selectedContact.name);
});
}
}
Here is my HTML file (The view I am attempting to bind to.:
<div id= 'contact-card' >
<header>
<button routerLink='/home'>< Contacts</button>
</header>
<section id= card-container>
<img id ="largeContactPhoto" onerror="onerror=null;src='../assets/User Large/User — Large.png';"
src={{selectedContact.largeImageURL}} />
<h1> {{selectedContact.name}} </h1>
<h2> {{selectedContact.companyName}} </h2>
<ul>
<hr>
<li class="contact-data">
<h3> Phone: </h3>
{{selectedContact.phone.home}}
<hr>
</li>
<li class="contact-data">
<h3> Phone: </h3>
{{selectedContact.phone.mobile}}
<hr>
</li>
<li class="contact-data">
<h3> Phone: </h3>
{{selectedContact.phone.work}}
<hr>
</li>
<li class="contact-data">
<h3> Address: </h3>
{{selectedContact.address.street}}<br>
{{selectedContact.address.city}},{{selectedContact.address.state}} {{selectedContact.address.zipcode}}
<hr>
</li>
<li class="contact-data">
<h3> Birthdate: </h3>
{{selectedContact.birthdate}}
<hr>
</li>
<li class="contact-data">
<h3> Email: </h3>
{{selectedContact.email}}
<hr>
</li>
</ul>
</section>
</div>
app.service.ts (where the click event data is being passed to app.component.ts:
import { Injectable } from '#angular/core';
import { Http, Response } from '#angular/http';
import { Observable } from 'rxjs/Observable';
import { Subject } from 'rxjs/Subject';
import 'rxjs/add/operator/map';
#Injectable()
export class ApiService {
//API URL
private url: string = 'assets/api/contacts.json';
public newContactSubject = new Subject<any>();
//Initialize HttpClient for request
constructor(private _http: Http) { }
//Pull JSON data from REST API
getContacts(): Observable<any> {
return this._http.get(this.url)
.map((response: Response) => response.json());
}
openSelectedContact(data) {
this.newContactSubject.next(data);
}
}
Sibling Component THIS IS WHERE THE CLICK EVENT HAPPENS* :
import { Component, OnInit } from '#angular/core';
import { Router } from '#angular/router';
import { ApiService } from '../api.service';
#Component({
selector: 'app-contacts-list',
templateUrl: './contacts-list.component.html',
styleUrls: ['./contacts-list.component.scss']
})
export class ContactsListComponent implements OnInit {
title : string = 'Contacts';
sortedFavorites: any[] = [];
sortedContacts: any[] = [];
errorMessage: string;
constructor (private _apiService: ApiService, private router: Router) {}
ngOnInit(){ this.getContacts()}
getContacts() {
this._apiService.getContacts()
.subscribe(
(contacts) => {
//Sort JSON Object Alphabetically
contacts.sort((a , b) => {
if (a.name > b.name) {return 1};
if (a.name < b.name) {return -1};
return 0;
})
//Build new Sorted Arrays
contacts.forEach( (item) => {
if (item.isFavorite) {
this.sortedFavorites.push(item);
} else {
this.sortedContacts.push(item);
}
});
});
}
openFavorite($event, i) { <--Click event coming in from HTML template
let selectedFavorite = this.sortedFavorites[i];
this._apiService.openSelectedContact(selectedFavorite); <--Routing this data to services.ts file
this.router.navigate(['/details']); <--Navigate to detailed view to see selected contact.
};
}
This binding will work with any other test variables that i put into my app.component.ts file and they get bounded to the page. I feel like this is the right syntax for it to be properly binding the object.properties, but it doesn't seem to be working.
What might I be missing on this? Thanks a lot in advance!!
EDIT One: I feel like I should also add that this exact same code was working before when I had my component routed to this component. It was only when I moved my files to a new component and created a different new that this started happening. Maybe it is isn’t imported correctly somewhere?
EDIT TWO: I have refactored the code in the original post and corrected my TypeScript declarations and removed this from my html template. I have placed my console.log(this.selectedContact.name) function inside my showContact() method and it does log the correct name once the name in the contacts list is clicked along side this error: ERROR TypeError: Cannot read property 'largeImageURL' of undefined. So it is logging this.selectedContact.name correctly and that variable isn't defined anywhere else in my application. I have added my app.service.ts file as well as my sibling component.ts file just to put this in context where the click event happens. I want the click event data to go from Sibling component --> Api Service.ts file --> Sibling component on a click event. This is very confusing to me why this isn't happening.
EDIT THREE
One other issue that I have noticed is that whenever I attempt to use the safe navigation operator to resolve this, my highlighting changes in my html template, making me think that it is breaking it.
versus this:
Notice the change in the </h1> highlighting? This has subsiquently made every open and closing tag show up in grey instead of the red now. I have never attempted to use the safe navigation operator, so I am unsure as to whether this is normal. I have tried it with different spacing around the {{ and }} and still no luck.
Are you expecting an array or an object? You should type exactly what you are getting from your service.
Here you mention an array:
selectedContact: any[] = [];
Here you mention an object.
<h1> {{this.selectedContact.name}} </h1>
Give a shot in your template with the json pipe.
{{ selectedContact | json }}
This will help you debug.
Also, because your data is displayed on the browser before it is received by your service, you will get an undefined variable. Either use ? or an *ngIf. (With the *ngIf, don't define your selectedContact as an array to start with)
<div id= 'contact-card' *ngIf="selectedContact">
or
<h1> {{this.selectedContact?.name}} </h1>

Get child component form value in parent component's form submission?

Note: since the problem is a little complex, the code is abstracted for readability
We have a <child-component> component template like this:
<select name="someName" #someID ngDefaultControl [(ngModel)]="someModel" (ngModelChange)="onChange(someID.value)">
<option *ngFor="let a of list" [ngValue]="a.key">{{a.value}}</option>
</select>
And the ts file is with output configuration:
#Component({
moduleId: module.id,
selector: 'child-component',
templateUrl: 'child-component.html',
outputs: ['someChildEvent']
})
export class ChildComponent {
someChildEvent = new EventEmitter<string>();
onChange(value) {
this.someChildEvent.emit(value);
}
}
Which we're calling in a <parent-component> like this:
<form #f="ngForm" (submit)="submit(f)" >
<child-component (childEvent)="childData=$event"></child-component>
<input type="submit" value="submit">
</form>
with .ts like:
export class ParentComponent {
childData;
submit(f) {
//How to access childData here?
}
}
Is it the correct implementation of the output configuration in Angular 2?
How do we access the value of the select's option from <child-component> on <parent-component>'s form submit to submit(f) function?
<child-component (childEvent)="childData=$event"></child-component>
the event name in here needs to match your method name so it should be:
<child-component (someChildEvent)="childData=$event"></child-component>
and if you like to send the object selected in your select box, change ngValue to that object and the change the model event accordingly:
[ngValue]="a"
(ngModelChange)="onChange($event)"

how to share data between two component using Event Emitter?

Could you please suggest how to add item in list when something enter in input field and then enter press.But these are different component .I want to share input field value to different component using #Input ,#Output ,EventEmitter.
I make one component .
<todo></todo>
here is ts file
import { Page,NavController,Modal } from 'ionic-angular/index';
import { Component, Input, Output, EventEmitter} from 'angular2/core';
#Component({
selector:'todo'
templateUrl:"addtodo.html",
})
export class AddToDO{
constructor() {
}
addItem(v){
alert(v.value)
}
}
here is my html
<label class="item item-input">
<span class="input-label" >Add Todo</span>
<input type="text" #todo placeholder="Add todo" (keyup.enter)="addItem(todo)">
</label>
I want to add item list when enter is press .so need to share data between component
http://plnkr.co/edit/N6aXDZXUr99MC6w77H6d?p=preview
I would leverage an #Output in your AddToDO component to trigger that an element was added. So you can catch it from the parent component and add the corresponding data in the list.
#Component({
selector:'todo'
templateUrl:"addtodo.html",
})
export class AddToDO{
#Output()
todoAdded:EventEmitter = new EventEmitter();
constructor() {
}
addItem(v){
alert(v.value)
this.todoAdded.emit(v);
}
}
and in the parent component template:
<todo (todoAdded)="addTodoInList($event)"></todo>
Here is the content of the addTodoInList method:
addTodoInList(todo) {
this.Todo.push(todo);
}
See this plunkr: http://plnkr.co/edit/mQtQIXIJwMfJSfNVHvac?p=preview.

Categories

Resources