I'm using angular2 swing in ionic in order make swiping cards. So after building, I'm getting cards one below one not in the stack format(as they get in tinder). Can someone help me in figuring it out. why are the cards are not in stack format? Here is my code.
<div swing-stack #myswing1 [stackConfig]="stackConfig" (throwoutleft)="voteUp(false)" (throwoutright)="voteUp(true)" id="card-stack" >
<ion-card #mycards1 swing-card *ngFor="let job of jdetails">
<div >
<img src="assets/imgs/lap.jpg" (click)="openPage()" id="tagimg">
<div class="textoncard title" >{{ job.company }}</div>
<div class="textoncard subt">{{ job.jobtitle }}</div>
<div class="textoncard time">2 days ago</div>
</div>
<ion-card-content>
<table>
<tr>
<td class="label">Location</td>
<td class="des">{{ job.location }}</td>
</tr>
<tr>
<td class="label">Type</td>
<td class="des">{{ job.jobtype }}</td>
</tr>
<tr>
<td class="label">salary</td>
<td class="des">{{ job.jobtype }}</td>
</tr>
<tr>
<td class="label">Description</td>
<td class="des">{{ job.jobdescrition }}</td>
</tr>
<tr>
<td class="label">Source</td>
<td class="des"><p style="color: purple;font-weight: bold;">Monster</p></td>
</tr>
</table>
<div id="endbtn">
<ion-buttons class="ionrow">
<button ion-button icon-only clear (tap)="tapEvent($event)" [ngStyle]="{'color': buttonColor}">
<ion-icon name="ios-heart"></ion-icon>
</button>
<button ion-button icon-only clear style="color: black" id="sharebtn">
<i class="fas fa fa-share-alt custom-share"></i>
</button>
</ion-buttons>
</div>
</ion-card-content>
</ion-card>
</div>
Here is ts file
export class FeedsPage {
#ViewChild('myswing1') swingStack: SwingStackComponent;
#ViewChildren('mycards1') swingCards: QueryList<SwingCardComponent>;
stackConfig: StackConfig;
recentCard: string = '';
cards: Array<any>;
buttonColor: string = '#F2F0F4';
public press: number = 0;
jobtitletosave: string;
showdropdown: boolean = false;
searchQuery: string = '';
items: string[];
jdetails: any;
constructor(public navCtrl: NavController,
public navParams: NavParams,
public modalCtrl: ModalController,
private nativePageTransitions: NativePageTransitions,
public jobdetail: JobsDataProvider
)
{
this.stackConfig = {
throwOutConfidence: (offsetX, offsetY, element: any) => {
return Math.min(Math.abs(offsetX) / (element.offsetWidth/2), 1);
},
transform: (element, x, y, r) => {
this.onItemMove(element, x, y, r);
},
throwOutDistance: (d) => {
return 800;
}
};
this.initializeItems();
}
ionViewDidLoad() {
console.log('ionViewDidLoad FeedsPage');
this.jobdetail.getJobDetails().then((data) => {
console.log(data);
this.jdetails = data;
});
}
openPage() {
let options: NativeTransitionOptions = {
direction: 'down',
duration: 100,
slowdownfactor: -1,
iosdelay: 50,
androiddelay: 50,
}
this.nativePageTransitions.fade(options);
this.navCtrl.push(JobDetailPage);
}
showAlert() {
let modal = this.modalCtrl.create(ModalPage);
modal.present();
}
ngAfterViewInit() {
// Either subscribe in controller or set in HTML
this.swingStack.throwin.subscribe((event: DragEvent) => {
event.target.style.background = '#ffffff';
});
}
onItemMove(element, x, y, r) {
let color = '';
const abs = Math.abs(x);
const min = Math.trunc(Math.min(16 * 16 - abs, 16 * 16));
const hexCode = this.decimalToHex(min, 2);
if (x > 0) {
color = '#' + hexCode + 'FF' + hexCode;
} else {
color = '#FF' + hexCode + hexCode;
}
element.style.background = color;
element.style['transform'] = `translate3d(0, 0, 0) translate(${x}px, ${y}px) rotate(${r}deg)`;
}
decimalToHex(d, padding) {
let hex = Number(d).toString(16);
const numPadding = typeof (padding) === 'undefined' || padding === null ? 2 : padding;
while (hex.length < numPadding) {
hex = '0' + hex;
}
return hex;
}
voteUp(like: boolean) {
}
tapEvent(e) {
this.press++;
if (this.press % 2 != 0 ) {
this.buttonColor = '#E24B4B';
}
else {
this.buttonColor = '#F2F0F4';
}
}
}
I want the cards
here is how I'm getting tem I want them as
Related
I am attempting to create a Gutenberg block to track exercise sets. I'm using a RichText component to allow users to edit default values in a table I pre-populate for them.
The block works well on the editor and, after saving, renders correctly in the post. However, when I reload the editor, I receive this error message: Block validation: Expected tag name 'thead', instead saw 'table'. It's almost like Gutenberg is stripping the table tag but leaving everything else.
Of course, that doesn't make sense, but I'm not sure what else it could be.
Here's my code, heavily edited for readability:
const { registerBlockType } = wp.blocks;
const { AlignmentToolbar, BlockAlignmentToolbar, BlockControls, RichText, useInnerBlockProps } = wp.blockEditor;
const { Component } = wp.element;
registerBlockType('bsd-strong-post/training-session', {
title: __('Strong Post', 'bsd-strong-post'),
description: __('Provides a short summary of a training session', 'bsd-strong-post'),
category: 'common',
icon: blockIcons.weight_lifting,
keywords: [
__('strength workout', 'bsd-strong-post'),
__('strong', 'bsd-strong-post'),
__('training', 'bsd-strong-post')
],
supports: {
html: true
},
attributes: {
/* ... */,
dayTemplateContent: {
type: 'string',
source: 'html',
selector: '.bsd-strong-post-training-template'
},
/* ... */
},
/* ... */
edit: class extends Component {
constructor(props) {
super(...arguments);
this.props = props;
/* ... */
this.dayTemplateHandler = this.dayTemplateHandler.bind(this);
this.onChangeBlockTemplate = this.onChangeBlockTemplate.bind(this);
}
/* ... */
dayTemplateHandler(new_val) {
const dayTemplateList = this.state.dayTemplateList;
let selectedDayTemplate = dayTemplateList.filter(item => {
return item.value == new_val;
})
if (selectedDayTemplate[0]['label']) {
this.props.setAttributes({
dayTemplateId: new_val,
dayTemplateName: selectedDayTemplate[0]['label']
});
}
this.getTemplate(new_val);
}
getTemplate(templateId) {
api.getDayTemplate(templateId)
.then((data) => {
if (!data.status || data.status == 0) {
return false;
};
if (!data.day_template) {
return false;
};
this.props.setAttributes({
dayTemplateContent: data.day_template.template_content
});
return data.day_template;
}).catch((err) => {
console.log('getTemplate caught error')
return false;
});
}
onChangeBlockTemplate(value) {
this.props.setAttributes({
dayTemplateContent: value
});
}
/* ... */
render() {
const { dayTemplateHandler, onChangeBlockTemplate, phaseControlHandler, programControlHandler, updateBlockAlignment, updateTextAlignment } = this;
const { block_alignment, dayTemplateId, dayTemplateName, dayTemplateContent, phaseId, phaseName, programAuthor, programId, programName, programPhases, text_alignment } = this.props.attributes;
/* ... */
return [
<InspectorControls>
<PanelBody title={ __('Basics', 'bsd-strong-post') }>
<SelectControl
label={ __('Day', 'bsd-strong-post') }
help={ __('The training session (e.g., Day One)', 'bsd-strong-post') }
value={ dayTemplateId }
options={ this.state.phaseTemplates }
onChange={ dayTemplateHandler }
/>
}
</PanelBody>
</InspectorControls>,
<div className='bsd-strong-post-block-editor'>
<div className={ this.props.className }>
<RichText
placeholder={ __('Log your lifts here') }
value={ dayTemplateContent }
multiline={ false }
onChange={ onChangeBlockTemplate }
className='bsd-strong-post-training-log'
/>
</div>
</div>
];
}
},
save: (props) => {
return (
<div className={ `align${props.attributes.block_alignment}` }>
<ul className='list-unstyled'style={{ textAlign: props.attributes.text_alignment }}>
<li>
<strong>{ __('Program', 'bsd-strong-post') }: </strong>
<span className='bsd-strong-post-program'>{ props.attributes.programName }</span>
</li>
<li>
<strong>{ __('Phase', 'bsd-strong-post') }: </strong>
<span className='bsd-strong-post-phase-ph'>{ props.attributes.phaseName }</span>
</li>
<li>
<strong>{ __('Day', 'bsd-strong-post') }: </strong>
<span className='bsd-strong-post-day-ph'>{ props.attributes.dayTemplateName }</span>
</li>
<li>
<strong>{ __('Author', 'bsd-strong-post') }: </strong>
<span className='bsd-strong-post-author-ph'>{ props.attributes.programAuthor }</span>
</li>
</ul>
<RichText.Content
value={ props.attributes.dayTemplateContent }
className='bsd-strong-post-training-log'
/>
</div>
)
}
});
Here's the console output on reload:
Content generated by 'save' function:
<div class="wp-block-bsd-strong-post-training-session alignwide"><ul class="list-unstyled"><li><strong>Program: </strong><span class="bsd-strong-post-program">Madcow</span></li><li><strong>Phase: </strong><span class="bsd-strong-post-phase-ph">Intermediate</span></li><li><strong>Day: </strong><span class="bsd-strong-post-day-ph">Day 1</span></li><li><strong>Author: </strong><span class="bsd-strong-post-author-ph">Madcow</span></li></ul>
<thead>
<tr>
<th scope="col">Exercise</th>
<th scope="col">Set 1</th>
<th scope="col">Set 2</th>
</tr>
</thead>
<tbody>
<tr class="bsd-strong-post-exercise-one">
<td class="bsd-strong-post-exercise-name">Squat</td>
<td class="bsd-strong-post-set-1">95 x 5</td>
<td class="bsd-strong-post-set-2">135 x 5</td>
</tr>
</tbody>
</div>
Content retrieved from post body:
<div class="wp-block-bsd-strong-post-training-session alignwide"><ul class="list-unstyled"><li><strong>Program: </strong><span class="bsd-strong-post-program">Madcow</span></li><li><strong>Phase: </strong><span class="bsd-strong-post-phase-ph">Intermediate</span></li><li><strong>Day: </strong><span class="bsd-strong-post-day-ph">Day 1</span></li><li><strong>Author: </strong><span class="bsd-strong-post-author-ph">Madcow</span></li></ul><table class='bsd-strong-post-training-template'>
<thead>
<tr>
<th scope='col'>Exercise</th>
<th scope='col'>Set 1</th>
<th scope='col'>Set 2</th>
</tr>
</thead>
<tbody>
<tr class='bsd-strong-post-exercise-one'>
<td class='bsd-strong-post-exercise-name'>Squat</td>
<td class='bsd-strong-post-set-1'>95 x 5</td>
<td class='bsd-strong-post-set-2'>135 x 5</td>
</tr>
</tbody>
</table></div>
I can see that the content displayed below Content generated by 'save' function: is missing the <table> and </table> tags. I've tried to work around this by adding tagName='table' in the RichText.Content properties inside the save function, but then the console shows duplicate <table> and </table> tags.
EDIT: The table is populated when a user makes a change to the Select control in InspectorControls. This action calls dayTemplateHandler, which among other things, calls getTemplate, a function that gets the content of the table from the database. Here's an example of that output (data.day_template.template_content):
<table class='bsd-strong-post-training-template'>
<thead>
<tr>
<th scope='col'>Exercise</th>
<th scope='col'>Set 1</th>
<th scope='col'>Set 2</th>
</tr>
</thead>
<tbody>
<tr class='bsd-strong-post-exercise-one'>
<td class='bsd-strong-post-exercise-name'>Squat</td>
<td class='bsd-strong-post-set-1'>95 x 5</td>
<td class='bsd-strong-post-set-2'>135 x 5</td>
</tr>
</tbody>
</table>
On reviewing the table template and considering the error, I suspect the issue is the selector of the dayTemplateContent attribute, .bsd-strong-post-training-template
The first time the content is saved, it successfully loads the template data from database and saves the complete table structure. When the content is reloaded, the block validator fails as the selector of dayTemplateContent reads in the child nodes of the table's css selector (which is thead) and doesn't match expected content. Ref: HTML example of blockquote/paragraphs
Try wrapping the <table> template with a <div class="bsd-strong-post-training-template"> or changing the selector.
I need to filter table rows by category so class filterTr is added to element <tr> but then element <tr> resizes in width and no longer aligns with element <th> above.
I don't know why this happens. The snippet below is a simplified version but the same thing happens here:
filterSelection("all")
function filterSelection(c) {
var x, i;
x = document.getElementsByClassName("filterTr");
if (c == "all") c = "";
for (i = 0; i < x.length; i++) {
w3RemoveClass(x[i], "show");
if (x[i].className.indexOf(c) > -1) w3AddClass(x[i], "show");
}
}
function w3AddClass(element, name) {
var i, arr1, arr2;
arr1 = element.className.split(" ");
arr2 = name.split(" ");
for (i = 0; i < arr2.length; i++) {
if (arr1.indexOf(arr2[i]) == -1) {element.className += " " + arr2[i];}
}
}
function w3RemoveClass(element, name) {
var i, arr1, arr2;
arr1 = element.className.split(" ");
arr2 = name.split(" ");
for (i = 0; i < arr2.length; i++) {
while (arr1.indexOf(arr2[i]) > -1) {
arr1.splice(arr1.indexOf(arr2[i]), 1);
}
}
element.className = arr1.join(" ");
}
var btnContainer = document.getElementById("sowClndr-filter");
var btns = btnContainer.getElementsByClassName("btn");
for (var i = 0; i < btns.length; i++) {
btns[i].addEventListener("click", function(){
var current = document.getElementsByClassName("active");
current[0].className = current[0].className.replace(" active", "");
this.className += " active";
});
}
/* Table filter */
.filterTr {
display: none;
}
.filterBtn {
margin-top:-10px!important;
background-color:rgba(55,175,75,1.00)!important;
color:rgba(255,255,255,1.00)!important;
border:1px solid rgba(55,175,75,1.00)!important;
text-align:left!important;
font-weight:400!important;
text-overflow:ellipsis!important;
white-space:nowrap!important;
overflow:hidden!important;
}
.filterBtn:hover {
background-color:rgba(255,255,255,0.00)!important;
color:rgba(0,145,255,1.00)!important;
border:1px solid rgba(0,145,255,1.00)!important;
}
.btn.active {
background-color:rgba(255,255,255,0.00)!important;
color:rgba(0,145,255,1.00)!important;
border:1px solid rgba(0,145,255,1.00)!important;
}
.show {
display: block;
}
/* Table styles */
.sowClndr-tr {
background-color:rgba(255,255,255,1.00)!important;
border:0!important;
}
.sowClndr-tr:hover {
background-color:rgba(55,175,75,0.15)!important;
border:0!important;
}
<div id="sowClndr-filter">
<button class="btn btn-primary filterBtn active" onclick="filterSelection('all')"> All selections</button>
<button class="btn btn-primary filterBtn" onclick="filterSelection('A')"> selection A</button>
<button class="btn btn-primary filterBtn" onclick="filterSelection('B')"> selection B</button>
</div>
<table id="myTable">
<tr class="header">
<th style="width:60%;">Name</th>
<th style="width:40%;">Country</th>
</tr>
<tr class="sowClndr-tr filterTr A">
<td>S1 fname lname</td>
<td>lorem ipsum</td>
</tr>
<tr class="sowClndr-tr filterTr B">
<td>lorem ipsum</td>
<td>lorem ipsum</td>
</tr>
</table>
SOLVED
The CSS style display:block; for class .show messes up the table layout because class .show is added to <tr> using JS to make it visible. The solution is to use CSS style display:table-row; instead, now it works. I did not know that this style existed untill now.
I want to add load more button in my project.I want to call an api on load more button and display the result.How i will implement this, in my case i am getting 200 result at a time because i have set limit 200 but i want a load more button in my code so that i can lazy load.i want to call api on button click.
Html
<div class="container">
<div class="row">
<div class="col-xs-12">
<div class="margin-20">
</div>
<form [formGroup]="transactionForm" (ngSubmit)="searchTransaction(transactionForm.value)" >
<div class="form-group col-xs-2">
<label>Workshop</label>
<select class="form-control" [(ngModel)]="selectedWorkShop" formControlName="workshops">
<option value="" selected>--select--</option>
<option *ngFor="let workshop of workshops" value= {{workshop.id}}>{{workshop.name}}</option>
</select>
<small *ngIf="!transactionForm.controls.workshops.valid" class="text-danger">Required</small>
</div>
<div class="form-group col-xs-2">
<label>Start Date</label>
<input class="form-control" placeholder="Choose Date" [ngModel]="startDate" formControlName="startDate" (focus)="toggleDatePicker1(true)"
readonly />
<date-picker *ngIf="showTimePicker1" [initDate]="startDate" (onDatePickerCancel)="toggleDatePicker1($event)" (onSelectDate)="setStartDate($event)"></date-picker>
<small *ngIf="!transactionForm.controls.startDate.valid" class="text-danger">Required</small>
</div>
<div class="form-group col-xs-2">
<label>End Date</label>
<input class="form-control" placeholder="Choose Date" [ngModel]="endDate" formControlName="endDate" (focus)="toggleDatePicker2(true)"
readonly />
<date-picker *ngIf="showTimePicker2" [initDate]="endDate" (onDatePickerCancel)="toggleDatePicker2($event)" (onSelectDate)="setEndDate($event)"></date-picker>
<small *ngIf="!transactionForm.controls.endDate.valid" class="text-danger">Required</small>
</div>
<!--<div class="form-group col-xs-2">
<label>From Date</label>
<input class="form-control" placeholder="Choose Date" [ngModel]="date" formControlName="date" (focus)="toggleDatePicker(true)"
readonly />
<date-picker *ngIf="showTimePicker" [initDate]="date" (onDatePickerCancel)="toggleDatePicker($event)" (onSelectDate)="setDate($event)"></date-picker>
</div>-->
<div class="margin-20 col-xs-12">
<button type="submit" class="btn btn-primary" [disabled]="!transactionForm.valid">Search</button>
<img *ngIf="loading" src="data:image/gif;base64,R0lGODlhEAAQAPIAAP///wAAAMLCwkJCQgAAAGJiYoKCgpKSkiH/C05FVFNDQVBFMi4wAwEAAAAh/hpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh+QQJCgAAACwAAAAAEAAQAAADMwi63P4wyklrE2MIOggZnAdOmGYJRbExwroUmcG2LmDEwnHQLVsYOd2mBzkYDAdKa+dIAAAh+QQJCgAAACwAAAAAEAAQAAADNAi63P5OjCEgG4QMu7DmikRxQlFUYDEZIGBMRVsaqHwctXXf7WEYB4Ag1xjihkMZsiUkKhIAIfkECQoAAAAsAAAAABAAEAAAAzYIujIjK8pByJDMlFYvBoVjHA70GU7xSUJhmKtwHPAKzLO9HMaoKwJZ7Rf8AYPDDzKpZBqfvwQAIfkECQoAAAAsAAAAABAAEAAAAzMIumIlK8oyhpHsnFZfhYumCYUhDAQxRIdhHBGqRoKw0R8DYlJd8z0fMDgsGo/IpHI5TAAAIfkECQoAAAAsAAAAABAAEAAAAzIIunInK0rnZBTwGPNMgQwmdsNgXGJUlIWEuR5oWUIpz8pAEAMe6TwfwyYsGo/IpFKSAAAh+QQJCgAAACwAAAAAEAAQAAADMwi6IMKQORfjdOe82p4wGccc4CEuQradylesojEMBgsUc2G7sDX3lQGBMLAJibufbSlKAAAh+QQJCgAAACwAAAAAEAAQAAADMgi63P7wCRHZnFVdmgHu2nFwlWCI3WGc3TSWhUFGxTAUkGCbtgENBMJAEJsxgMLWzpEAACH5BAkKAAAALAAAAAAQABAAAAMyCLrc/jDKSatlQtScKdceCAjDII7HcQ4EMTCpyrCuUBjCYRgHVtqlAiB1YhiCnlsRkAAAOwAAAAAAAAAAAA=="
/>
</div>
</form>
</div>
</div>
</div>
<br><br>
<div class="container">
<div class="row">
<div class="col-xs-12">
<p *ngIf="isNoresult"><em>No Result Found</em></p>
<table class='table table-hover' *ngIf="transactions">
<thead>
<tr>
<th>User ID</th>
<th>Txn ID</th>
<th>Order Id</th>
<th>Mode</th>
<th>Transaction Type</th>
<th>Amount</th>
<th>Date</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let transaction of transactions ">
<td>{{ transaction.user_id }}</td>
<td>{{ transaction.txn_id }}</td>
<td>{{ transaction.order_id }}</td>
<td>{{ transaction.mode }}</td>
<td>{{ transaction.transaction_type }}</td>
<td>{{ transaction.amount | number : '1.2-2' }}</td>
<td>{{ transaction.date * 1000 | date:'dd-MM-yyyy' }}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
Component
import { Component, OnInit } from '#angular/core';
import { FormGroup, AbstractControl, FormBuilder, Validators } from '#angular/forms';
import { Router } from '#angular/router';
import{DatePipe} from '#angular/common';
import { AlertService } from '../../../_services/index'
import { TransactionDetailsServices } from './transactionDetails.service';
// import { CustomerFilter, Customer } from '../models/index';
#Component({
selector: 'transactionDetails',
templateUrl: './transactionDetails.html'
})
export class TransactionDetails implements OnInit {
public transactionForm :FormGroup;
public workshops:any="";
public selectedWorkShop="";
public showTimePicker1:boolean;
public showTimePicker2:boolean;
public startDate=new Date();
public endDate=new Date();
public transactions:any;
public loading:boolean;
public isNoresult:boolean;
public offset:number=0;
constructor(
private fb:FormBuilder,
private alertService: AlertService,
private transactionDetailsService: TransactionDetailsServices,
private datePipe:DatePipe
) {
}
public phone: any;
ngOnInit() {
// const phoneRegex = `^[2-9]{2}[0-9]{8}$`;
// this.searchCustomerForm = this.fb.group({
// phone: ['', [Validators.required, Validators.pattern(phoneRegex)]],
// phoneCC: [{value:'',disabled:true}]
// });
// this.orderForm = this.fb.group({
// categories: this.listCategory()
// });
this.transactionForm=this.fb.group({
workshops:[this.listWorkshop(),Validators.required],
startDate:['',Validators.required],
endDate:['',Validators.required]
})
}
listWorkshop() {
this.weDoShoesCMSService.listWorkshop().subscribe(res => {
this.workshops = res;
this.selectedWorkShop="";
console.log(res);
},
err => {
this.alertService.error(err);
});
}
toggleDatePicker1(status: boolean): void {
this.showTimePicker1 = status;
}
toggleDatePicker2(status: boolean): void {
this.showTimePicker2 = status;
}
setStartDate(date: any): void {
this.startDate = date;
console.log(this.startDate);
}
setEndDate(date: any): void {
this.endDate = date;
console.log(this.endDate);
}
searchTransaction(model:any){
this.loading=true;
console.log(model);
model.startDate=this.filterDate(model.startDate);
model.endDate=this.filterDate(model.endDate);
console.log(model.startDate);
console.log(model.endDate);
this.transactionDetailsService.searchTransaction(model).subscribe(res=>{
this.transactions=res;
if(res==null){
this.isNoresult=true;
this.loading=false;
}
else{
this.isNoresult=false;
console.log(res);
this.loading=false;
}
},
error=>{
this.alertService.error(error);
this.loading=false;
});
}
filterDate(date){
return Date.parse(this.datePipe.transform(date, 'yyyy-MM-dd'))/1000;
}
convertDate(date){
return Date.parse(this.datePipe.transform(date,''))
}
}
Service
import {Component} from '#angular/core'
import { Injectable } from '#angular/core';
import { Http, Headers, Response, RequestOptions } from '#angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import { Networks } from '../../networks/wedoshoes.networks';
#Injectable()
export class TransactionDetailsServices{
constructor(private http:Http) {
}
searchTransaction(model:any){
let requestUrl=this.generateUrl(model);
let headers = this.httpHelper(true);
let options = new RequestOptions({ headers: headers });
return this.http.get(requestUrl, options)
.map((response: Response) => response.json())
.catch((error: any) => Observable.throw(error || JSON.parse(error._body)));
}
generateUrl(model:any):any{
let requestUrl=Networks.OMS_BASE_URL+"/workshops/"+model.workshops+"/orders/payments?"+
"start_date="+model.startDate+"&end_date="+model.endDate+"&offset=0&"+"limit=200";
console.log(requestUrl);
return requestUrl;
}
httpHelper(isSecure: boolean) {
let headers = new Headers({ 'Content-Type': 'application/json', 'Accept': 'application/json' });
if (isSecure) {
headers.append("Authorization", localStorage.getItem('token'));
headers.append("X-UserID", localStorage.getItem('userId'));
}
return headers;
}
}
LoadMoreElement(){
this.loadResult=true;
console.log(this.loadResult);
this.calculateOffset();
this.findMoreTransaction(this.formOutput);
}
calculateOffset(){
this.offset=this.offset+this.limit;
}
findMoreTransaction(model:any){
this.transactionDetailsService.searchTransaction(model,this.offset,this.limit).subscribe(res=>{
console.log(res);
if(res==null){
this.alertService.success("No Record Found");
this.loading=false;
this.loadResult=false;
}
else{
if(this.transactions==null){
this.transactions=[];
this.loading=false;
}
else{
this.loadResult=false;
}
this.transactions=this.transactions.concat(res);
// this.fillTransaction();
console.log(this.transactions);
}
},
error=>{
this.alertService.error(error);
this.loading=false;
});
}
}
On a bootstrap based web page I'm displaying the following table:
This was generated with the following code:
<div class="row">
<div class="col-lg-12">
<div class="table-responsive">
<table class="table table-bordered table-hover table-striped">
<thead>
<tr>
<th class="text-right success">Count</th>
<th class="text-right success">Lower</th>
<th class="text-right success">Upper</th>
<th class="text-right success">Price</th>
<th class="text-right success">Cost</th>
</tr>
</thead>
<tbody>
#foreach (var dataRow in staffelData)
{
var differenceWithUpper = 0;
if (dataRow.Upper.HasValue)
{
differenceWithUpper = countValue - dataRow.Upper.Value;
}
else
{
differenceWithUpper = -1;
}
var cost = 0.0;
var inScope = 0;
if (differenceWithUpper >= 0)
{
inScope = dataRow.Upper.Value;
}
else
{
if (countValue >= dataRow.Lower.Value)
{
inScope = countValue - dataRow.Lower.Value;
}
}
cost = inScope * Decimal.ToDouble(#dataRow.PnrFee);
<tr>
<td class="text-right fit">#pnrsInScope</td>
#if (#dataRow.Lower.HasValue)
{
<td class="text-right fit">#dataRow.Lower.Value</td>
}
else
{
<td class="text-right fit">N/A</td>
}
#if (#dataRow.Upper.HasValue)
{
<td class="text-right fit">#dataRow.Upper.Value</td>
}
else
{
<td class="text-right fit">N/A</td>
}
<td class="text-right fit">#dataRow.Fee #dataRow.Currency</td>
<td class="text-right fit">#cost #dataRow.Currency</td>
</tr>
}
</tbody>
</table>)
</div>
</div>
</div>
I still need to add one feature though: I have to display an estimated value in the same table.
The estimated value is based on the average, say we have 25 orders a day, then on day you'd expect to have 250 orders. This 250 is the value I want to display on the same table.
I was thinking to draw a line # the level in the table the estimated value can be found, and adding a label to the line.
Could anyone here explain me how to best get this done?
Not sure if you would count this as a 'line' but I believe it's a suitable solution to your problem. Just change the class of your <tr> for the average row.
#foreach (var dataRow in staffelData)
{
var differenceWithUpper = 0;
if (dataRow.Upper.HasValue)
{
differenceWithUpper = countValue - dataRow.Upper.Value;
}
else
{
differenceWithUpper = -1;
}
var cost = 0.0;
var inScope = 0;
if (differenceWithUpper >= 0)
{
inScope = dataRow.Upper.Value;
}
else
{
if (countValue >= dataRow.Lower.Value)
{
inScope = countValue - dataRow.Lower.Value;
}
}
cost = inScope * Decimal.ToDouble(#dataRow.PnrFee);
#if (...this row is the average...){
<tr class='average-row'>
} else {
<tr>
}
<td class="text-right fit">#pnrsInScope</td>
#if (#dataRow.Lower.HasValue)
{
<td class="text-right fit">#dataRow.Lower.Value</td>
}
else
{
<td class="text-right fit">N/A</td>
}
#if (#dataRow.Upper.HasValue)
{
<td class="text-right fit">#dataRow.Upper.Value</td>
}
else
{
<td class="text-right fit">N/A</td>
}
<td class="text-right fit">#dataRow.Fee #dataRow.Currency</td>
<td class="text-right fit">#cost #dataRow.Currency</td>
</tr>
}
and then add a CSS rule for average-row
.average-row{
background-color: green;
}
UPDATE:
See the answer here
Linethrough/strikethrough a whole HTML table row
So for you
CSS:
table {
border-collapse: collapse;
}
td {
position: relative;
padding: 5px 10px;
}
tr.strikeout td:before {
content: " ";
position: absolute;
top: 50%;
left: 0;
border-bottom: 1px solid #111;
width: 100%;
}
HTML:
#foreach (var dataRow in staffelData)
{
var differenceWithUpper = 0;
if (dataRow.Upper.HasValue)
{
differenceWithUpper = countValue - dataRow.Upper.Value;
}
else
{
differenceWithUpper = -1;
}
var cost = 0.0;
var inScope = 0;
if (differenceWithUpper >= 0)
{
inScope = dataRow.Upper.Value;
}
else
{
if (countValue >= dataRow.Lower.Value)
{
inScope = countValue - dataRow.Lower.Value;
}
}
cost = inScope * Decimal.ToDouble(#dataRow.PnrFee);
#if (...this row is the average...){
<tr class="strikeout">
} else {
<tr>
}
<td class="text-right fit">#pnrsInScope</td>
#if (#dataRow.Lower.HasValue)
{
<td class="text-right fit">#dataRow.Lower.Value</td>
}
else
{
<td class="text-right fit">N/A</td>
}
#if (#dataRow.Upper.HasValue)
{
<td class="text-right fit">#dataRow.Upper.Value</td>
}
else
{
<td class="text-right fit">N/A</td>
}
<td class="text-right fit">#dataRow.Fee #dataRow.Currency</td>
<td class="text-right fit">#cost #dataRow.Currency</td>
</tr>
}
i have table with data and data populated by knockout js foreach bind.
i would like to know how to access specific table row's data when it gets updated.
if i could access table row then could add css class to that tr. my objective is to do bit color animation for a row which will be updated just clicking on button. when any data will be push to table row clicking on "Update Data" button then i want to add a class to that table row and after few minute remove that class too. hence i am new so no logic is coming to my mind to achieve this....any help would be appreciated. thanks
jsfiddle http://jsfiddle.net/62Ls6x9n/157/
full code
<button data-bind="click: AddNewData">Add New Data</button>
<button data-bind="click: UpdateDataByIds">Update Data</button>
<br><br>
<table class="imagetable">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Price</th>
<th>Status</th>
<th>Edit</th>
<th>Delete</th>
</tr>
</thead>
<tbody data-bind="foreach: Stocks">
<tr>
<td data-bind="text: id"></td>
<td data-bind="text: name"></td>
<td data-bind="text: price"></td>
<td data-bind="text: status"></td>
<td>edit</td>
<td>delete</td>
</tr>
</tbody>
</table>
table.imagetable {
font-family: verdana,arial,sans-serif;
font-size:11px;
color:#333333;
border-width: 1px;
border-color: #999999;
border-collapse: collapse;
}
table.imagetable th {
background:#b5cfd2 url('cell-blue.jpg');
border-width: 1px;
padding: 8px;
border-style: solid;
border-color: #999999;
}
table.imagetable td {
background:#dcddc0 url('cell-grey.jpg');
border-width: 1px;
padding: 8px;
border-style: solid;
border-color: #999999;
}
var StockItem = function(_id, _name, _price, _status){
var self = this;
self.id = ko.observable(_id);
self.name = ko.observable(_name);
self.price = ko.observable(_price);
self.status = ko.observable(_status);
};
var data= [
new StockItem("12345", "Acme Widget 1", "£25.99", "In Stock"),
new StockItem("67890", "Acme Widget 2", "£28.99", "In Stock"), new StockItem("11123","Acme Widget 3","£15.99", "In Stock"),
new StockItem("14156", "Acme Widget 4", "£33.99", "In Stock")
];
var NewData = [new StockItem("99999", "HSL Limited", "£78.99", "In Stock")];
var appViewModel = function()
{
var self = this;
self.Stocks = ko.observableArray(data);
self.AddNewData = function(){
self.Stocks.push.apply(self.Stocks,NewData);
};
self.DeleteItem = function(dataContext){
var itemToDelete = dataContext;
self.Stocks.remove(itemToDelete);
}
self.UpdateDataByIds = function(){
var id1 = '11123';
var id2 = '12345';
self.UpdateById(id1,null,null,"Out of Stock");
self.UpdateById(id2,null,"31.45",null);
};
self.UpdateById = function(_id, _name, _price, _status){
var matchedItem = ko.utils.arrayFirst(self.Stocks(), function(item) {
return item.id() === _id;
});
if (matchedItem != null){
if (_name != null) matchedItem.name(_name);
if (_price != null) matchedItem.price(_price);
if (_status != null) matchedItem.status(_status);
}
};
self.UpdateData = function(dataContext){
var itemToEdit = dataContext;
itemToEdit.status("Out of Stock");
};
};
var vm = new appViewModel();
ko.applyBindings(vm);
You can add a Mutated array to your view-model:
self.Mutated = ko.observableArray();
And upon updating / adding, add the item id to the array:
self.Mutated.push(_id);
Then in your HTML, have a mutated class on each <TR> that is indeed mutated:
<tr data-bind="css: { mutated: $root.Mutated.indexOf(id()) > -1 }">
And the CSS:
table.imagetable tr.mutated td { background-color: red; }
See Fiddle