Try to build own Angular table components but false HTML structure - javascript

I try to write my own Angular table components (table-container, table-row and table-item)
This should look like this
<app-table-container>
<app-table-row>
<app-table-item></app-table-item>
<app-table-item></app-table-item>
<app-table-item></app-table-item>
</app-table-row>
</app-table-container>
table-container.component.ts
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-table-container',
templateUrl: './table-container.component.html',
styleUrls: ['./table-container.component.scss']
})
export class TableContainerComponent implements OnInit {
constructor() { }
ngOnInit() {
}
}
table-container.component.html
<table border="1">
<thead>
<tr>
<th>Header 1</th>
<th>Header 2</th>
<th>Header 3</th>
</tr>
</thead>
<tbody>
<tr>
<ng-content></ng-content>
</tr>
</tbody>
</table>
table-row.component.ts
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-table-row',
templateUrl: './table-row.component.html',
styleUrls: ['./table-row.component.scss']
})
export class TableRowComponent implements OnInit {
constructor() { }
ngOnInit() {
}
}
table-row.component.html
<tr>
<td>Cell 1.1</td>
<td>Cell 1.2</td>
<td>Cell 1.3</td>
</tr>
<tr>
<td>Cell 2.1</td>
<td>Cell 2.2</td>
<td>Cell 2.3</td>
</tr>
and the app.component.ts
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {
title = 'testing-project';
public tableListObjects: any[] = [
{
name: {
forename: 'Jens',
surname: 'Vial'
},
age: 32,
job: 'Software Engineer',
vacation: false
},
{
name: {
forename: 'Hans',
surname: 'Peter'
},
age: 22,
job: 'Electrican',
vacation: true
}];
ngOnInit(): void {
}
}
and the app.component.html
<app-table-container>
<app-table-row></app-table-row>
</app-table-container>
for now, without the app-table-item component because the problem is in the app-table-row-component.
The problem is, that the table-structure is false.
I expect a table with 3 columns header 1 - 3 and two rows with cell 1.1 - 1.3 and 2.1 - 2.3
Instead the cells 1.1 - 1.3 and 2.1 - 2.3 are in the first column from header 1 see the image.
I have absolutely no idea why this happens. Can anyone tell me, at which point I make a mistake?
The DOM looks like this

I don't know if is you're looking for, but if you don't want to create addicional tags, you can use the way
<tr app-table-row></tr>
In the stackblitz has an example, but the app becomes like
<app-table-container>
<tr app-table-row>
<td app-table-cell>cell 1</td>
<td app-table-cell>cell 1</td>
<td app-table-cell>cell 1</td>
</tr>
</app-table-container>
the templates of app-table-row and app-table-cell are simple
<ng-content></ng-content>

Related

ERROR DOMException: Failed to execute 'setAttribute' on 'Element': '{{' is not a valid attribute name

Before the question, code is not completed yet so some methods are empty and *ngIf directives might be wrong (logic-wise, not syntax-wise). But even without them I got the same error so I didn't bother to remove them for now.
I'm following a angular course and expecting a screen like this when I click any of the edit buttons or create button:
Course-version
But after loading page without any errors, if I click any of the buttons (create or edit), I'm getting this error on the console and can't find why after a long try:
my-version
Similar problems I found on Stackoverflow mostly caused of simple syntax errors but I couldn't find any syntax issues with my code so far. Maybe someone will see the issue and correct me.
You can find all the codes below.
Here is my edit-task.component.html
<div *ngIf="task">
<h2 {{ task.taskName }}></h2>
<div>
Task ID:
<input [(ngModel)]="task.taskId" placeholder="Task ID"/>
</div>
<div>
Name:
<input [(ngModel)]="task.taskName" placeholder="Name"/>
</div>
<div>
Responsible ID:
<input [(ngModel)]="task.responsibleId" placeholder="Responsible ID"/>
</div>
<button (click)="updateTask(task)" *ngIf="task.taskId != null">Save</button>
<button (click)="deleteTask(task)" *ngIf="task.taskId != null">Delete</button>
<button (click)="createTask(task)" *ngIf="task.taskId == null">Create</button>
</div>
Here is app.component.html
<button (click)="initNewTask()">Create new task</button>
<table>
<thead>
<th>Task ID: </th>
<th>Task Name: </th>
<th>Resp ID: </th>
<th></th>
</thead>
<tbody>
<tr *ngFor="let task of tasks" >
<td>{{ task.taskId }}</td>
<td>{{ task.taskName }}</td>
<td>{{ task.responsibleId }}</td>
<td><button (click)="editTask(task)">Edit</button></td>
</tr>
</tbody>
</table>
<app-edit-task [task]="taskToEdit"></app-edit-task>
Here is edit-task.component.ts
import { Component, Input, OnInit } from '#angular/core';
import { Task } from 'src/app/models/task';
#Component({
selector: 'app-edit-task',
templateUrl: './edit-task.component.html',
styleUrls: ['./edit-task.component.css']
})
export class EditTaskComponent implements OnInit {
#Input() task?: Task;
constructor() { }
ngOnInit(): void {
}
updateTask(task:Task){
}
deleteTask(task:Task){
}
createTask(task:Task){
}
}
And here is app.component.ts
import { TaskService } from './services/task.service';
import { Task } from './models/task';
import { Component } from '#angular/core';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
tasks: Task[] = [];
taskToEdit?: Task;
constructor(private taskService: TaskService){}
ngOnInit() : void {
this.taskService
.getTasks()
.subscribe((result: Task[]) => (this.tasks = result));
}
initNewTask(){
this.taskToEdit = new Task();
}
editTask(task: Task){
this.taskToEdit = task;
}
}
Comes from
<h2 {{ task.taskName }}>
In edit-task.component.html
I don't know exactly what you tried to do but that can't work

Sort content on page Angular

I have a component and table.
I get an object from the server and display it in the table. I want to add sort buttons that change the information displayed in the table by type.
This is my table-components:
<app-home-modal-button></app-home-modal-button>
<app-home-button></app-home-button>
<div class="searchBox">
<input type="text" class="searchBoarder"/>
<i class="fas fa-search"></i>
</div>
<div class="table-container">
<table class="table">
<thead>
<tr class="table-nav">
<th scope="col">שנה</th>
<th scope="col">סוג הדוח</th>
<th scope="col">ח.פ</th>
<th scope="col">שם החברה</th>
</tr>
</thead>
<tbody>
<ng-container *ngFor="let tax of currentPage">
<tr>
<td>{{tax.year}}</td>
<td>{{tax.type}}</td>
<td>{{tax.cid}}</td>
<td>{{tax.company}}</td>
</tr>
</ng-container>
</tbody>
</table>
<div class="table-footer">
<pagination class="pagination" nextText=">" previousText="<" [totalItems]="totalItems" (pageChanged)="pageChanged($event)"> </pagination>
</div>
</div>
components ts:
import { Component, OnInit } from '#angular/core';
import { CompanyService } from '../../../../core/services/company.service';
import { Tax } from 'src/app/entity/tax.entity'
#Component({
selector: 'app-taxreports',
templateUrl: './taxreports.component.html',
styleUrls: ['./taxreports.component.sass']
})
export class TaxreportsComponent implements OnInit {
constructor(private service: CompanyService) {
}
taxList: Tax[];
totalItems: Number;
currentPage: Tax[];
page: Number = 1;
ngOnInit() {
this.service.getTaxList().subscribe(data => {
this.taxList = data;
this.totalItems = data.length;
this.currentPage = data.slice(0, 10)
}, error => {
console.log(error);
})
}
pageChanged(event) {
const startItem = (event.page - 1) * event.itemsPerPage;
const endItem = event.page * event.itemsPerPage;
this.currentPage = this.taxList.slice(startItem, endItem);
}
}
The problem is that i dont want to sort All the length of the object.
I want the sorting done only on the information shown in the table, because the information is divided into several pages using pagination.

Angular with TypeScript: Unexpected behavior in contenteditable <td> element in HTML <table> with (blur) upon first text entry

I encountered an unexpected behavior with contenteditable <td> element inside HTML <table> under Angular with TypeScript.
Here are steps to reproduce:
Click on any of the two table cells
Enter some text (e.g. "abc")
Click on the other table cell
Expected: the text in the cell is "abc"
Observed: the text in the cell is "abcabc" (the text is doubled, two text nodes are added to DOM instead of one updated)
Note: the above is observed only if the cells are empty, i.e. null or ""(empty string) as initial value. If one deletes the contents and adds text again - all works as expected (no doubling, see what you type)
Can someone explain this behavior and suggest solution (without changing <td> to <input>, i.e. preserving the <table> approach). Thank you.
Here is Stackblitz
app.component.html
<table>
<tr>
<th>Name</th>
<th>Age</th>
</tr>
<tr>
<td contenteditable="true" (blur)="update(data, 'name', $event)">{{data?.name}}</td>
<td contenteditable="true" (blur)="update(data, 'age', $event)">{{data?.age}}</td>
</tr>
</table>
Data: name[{{data?.name}}], age[{{data?.age}}]
app.component.ts
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
public data = { name: null, age: null};
public update(data, prop, ev) {
data[prop] = ev.target.textContent; // <-- !!!
}
}
Try this
<table>
<tr>
<th>Name</th>
<th>Age</th>
</tr>
<tr>
<td contenteditable="true" [textContent]="data?.name" (input)="data['name']=$event.target.textContent"></td>
<td contenteditable="true" [textContent]="data?.age" (input)="data['age']=$event.target.textContent"></td>
</tr>
</table>
use textContent input and input output on the td.
https://stackblitz.com/edit/zaggi-angular-table-td-issue-og3ore?file=src/app/app.component.html
in your html edit these lines
<tr>
<td contenteditable="true" (blur)="update(data, 'name', $event)"></td>
<td contenteditable="true" (blur)="update(data, 'age', $event)"></td>
</tr>
component.ts
text: any;
public update(data, prop, ev)
{
this.text = ev.target.textContent;
ev.target.textContent = '';
ev.target.textContent = this.text;
data[prop] = this.text;
}
<table>
<tr>
<th>Name</th>
<th>Age</th>
</tr>
<tr>
<td contenteditable="true" (blur)="update(data, 'name', $event)" value="data?.name"></td>
<td contenteditable="true" (blur)="update(data, 'age', $event)" value="data?.name"></td>
</tr>
</table>
setting the value property will fix the problem.

Using ngx-pagination on reusable component

I am attempting to use ngx-pagination on a reusable datatable component, however the change in one table is effecting the change in other tables on the page. How can I assure pagination events are only occurring on one component at a time?
table.component.html
<table>
<thead>
<tr>
<th *ngFor="let col of cols">
<label>{{col.header}}</label>
</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let row of data | paginate: { itemsPerPage: 6,
currentPage: p }">`
<td *ngFor="let col of cols">
{{row[col.prop]}}
</td>
</tr>
</tbody>
</table>
<pagination-controls
class="my-pagination"
(pageChange)="p = $event">
</pagination-controls>
table.component.ts
#Component({
selector: 'app-data-table',
templateUrl: './data-table.component.html',
styleUrls: ['./data-table.component.css']
})
export class DataTableComponent {
#Input() data
#Input() cols
p: number = 1
}

i am coding ..todo task manger in Angular2.... having to update select option value ....in localStorage

Here is my problem regarding to-do task management.
I want to update an option value in select selector when the (change) event is triggered.
there are 2 Component
//app.component.ts
//array object
this.dataArr[this.counter] = {id: this.task_ID, name: this.t_name, msg: this.t_msg, date: this.task_date};
//console.log(this.counter);
console.log(this.dataArr[this.counter]);
//local storage
if (typeof(Storage) !== "undefined") {
localStorage.setItem("taskM", JSON.stringify(this.dataArr.reverse())); //put object array in reverse order to show latest object at top position
this.myObj = JSON.parse(localStorage.getItem("taskM"));
}
in this component I want to change and save select option value to localStorage
//task-form.component.ts.
import { Component, OnInit, Input, Output } from '#angular/core';
import { AppComponent } from './app.component';
#Component({
selector: 'task-data',
template: `<h3>List of Task</h3>
<div class="table-responsive">
<table class="table table-striped">
<thead>
<tr>
<th>Task Id</th>
<th>Task Title</th>
<th>Description</th>
<th>Date</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let hero of taskMM">
<td> {{ hero.id }} </td>
<td> {{ hero.name }} </td>
<td> {{ hero.msg }} </td>
<td> {{ hero.date }} </td>
<td>
<select class="form-control">
<option *ngFor="let p of taskStatus"[value]="p"> {{p}}</option>
</select>
</td>
</tr>
</tbody>
</table>
</div>
`
})
export class TaskFormComponent {
taskStatus: string[];
taskMM: string[] = JSON.parse(localStorage.getItem("taskM"));
#Input('task-s') t_status: string;
#Input() data1: any= [];
onChange(deviceValue) {
console.log(deviceValue);
}
ngOnInit() {
console.log('this is ngOnInit ');
}
constructor() {
this.taskStatus = ['Started', 'Pending', 'Completed'];
}
}
<select (change)="onChange($event.target.value)" class="form-control">
<option *ngFor="let p of taskStatus"[value]="p"> {{p}}</option>
</select>
onChange($event) {
localStorage.setItem("taskM", $event);
}

Categories

Resources