Speed up record Load time laravel using Datatable - database

I am working with laravel project which uses a mysql database. I have 40,000 record in my database, it's take too much time around 20 min to load page. following is the function i use to get data.
plase check my code and help me to solve this issue.
Code is here
CustomerController
public function index()
{
//
abort_if(Gate::denies('customer_access'), Response::HTTP_FORBIDDEN, '403 Forbidden');
$customers = Customer::all();
return view('admin.customers.index', compact('customers'));
}
IndexController
#extends('layouts.admin')
#section('content')
#can('customer_create')
<div style="margin-bottom: 10px;" class="row">
<div class="col-lg-12">
<a class="btn btn-success" href="{{ route("admin.customers.create") }}">
{{ trans('global.add') }} {{ trans('cruds.customer.title_singular') }}
</a> | <a class="btn btn-success" href="importcustomer">
Import or Export
</a>
</div>
</div>
#endcan
<div class="card">
<div class="card-header">
{{ trans('cruds.customer.title_singular') }} {{ trans('global.list') }}
</div>
<div class="card-body">
<div class="table-responsive">
<table id="tabls" width="100%" class=" table table-bordered table-striped table-hover datatable datatable-User">
<thead>
<tr>
<th class="small-col">
</th>
<th class="small-col">
{{ trans('cruds.customer.fields.cid') }}
</th>
<th class="big-col">
{{ trans('cruds.customer.fields.cname') }}
</th>
<th class="big-col">
{{ trans('cruds.customer.fields.address') }}
</th>
<th class="big-col">
{{ trans('cruds.customer.fields.county') }}
</th>
<th class="big-col">
{{ trans('cruds.customer.fields.country') }}
</th>
<th class="big-col">
{{ trans('cruds.customer.fields.pcode') }}
</th>
<th class="big-col">
{{ trans('cruds.customer.fields.phone') }}
</th>
<th class="big-col">
{{ trans('cruds.customer.fields.mobile') }}
</th>
<th class="big-col">
{{ trans('cruds.customer.fields.email') }}
</th>
<th class="big-col">
{{ trans('cruds.customer.fields.web') }}
</th>
<th class="big-col">
{{ trans('cruds.customer.fields.mcat') }}
</th>
<th class="big-col">
{{ trans('cruds.customer.fields.scat') }}
</th>
<th class="small-col">
{{ trans('cruds.customer.fields.business') }}
</th>
<th class="big-col">
{{ trans('cruds.customer.fields.lead') }}
</th>
<th class="big-col">
{{ trans('cruds.customer.fields.rep') }}
</th>
</tr>
</thead>
<tbody>
#foreach($customers as $key => $supplier)
<tr data-entry-id="{{ $supplier->id }}">
<td>
#can('customer_show')
<a class="btn btn-xs btn-primary" href="{{ route('admin.customers.show', $supplier->id) }}">
{{ trans('global.view') }}
</a>
#endcan
#can('customer_edit')
<a class="btn btn-xs btn-info" href="{{ route('admin.customers.edit', $supplier->id) }}">
{{ trans('global.edit') }}
</a>
#endcan
#can('customer_delete')
<form action="{{ route('admin.customers.destroy', $supplier->id) }}" method="POST" onsubmit="return confirm('{{ trans('global.areYouSure') }}');" style="display: inline-block;">
<input type="hidden" name="_method" value="DELETE">
<input type="hidden" name="_token" value="{{ csrf_token() }}">
<input type="submit" class="btn btn-xs btn-danger" value="{{ trans('global.delete') }}">
</form>
#endcan
</td>
<td>
{{ $supplier->cid ?? 'NA' }}
</td>
<td>
{{ $supplier->cname ?? '' }}
</td>
<td>
{{ $supplier->address ?? '' }}
</td>
<td>
{{ $supplier->county ?? '' }}
</td>
<td>
{{ $supplier->country ?? '' }}
</td>
<td>
{{ $supplier->pcode ?? '' }}
</td>
<td>
{{ $supplier->phone ?? '' }}
</td>
<td>
{{ $supplier->mobile ?? '' }}
</td>
<td>
{{ $supplier->email ?? '' }}
</td>
<td>
{{ $supplier->web ?? '' }}
</td>
<td>
{{ $supplier->mcat ?? '' }}
</td>
<td>
{{ $supplier->scat ?? '' }}
</td>
<td>
{{ $supplier->business ?? '' }}
</td>
<td>
{{ $supplier->lead ?? '' }}
</td>
<td>
{{ $supplier->rep ?? '' }}
</td>
</tr>
#endforeach
</tbody>
</table>
</div>
</div>
</div>
<style>
.small-col {
width: 100px !important;
}
.big-col {
width: 200px !important;
}
table#tabls{
table-layout:fixed;
}</style>
#endsection
#section('scripts')
#parent
<script>
$(function () {
let dtButtons = $.extend(true, [], $.fn.dataTable.defaults.buttons)
#can('customer_delete')
let deleteButtonTrans = '{{ trans('global.datatables.delete') }}'
let deleteButton = {
text: deleteButtonTrans,
url: "{{ route('admin.users.massDestroy') }}",
className: 'btn-danger',
action: function (e, dt, node, config) {
var ids = $.map(dt.rows({ selected: true }).nodes(), function (entry) {
return $(entry).data('entry-id')
});
if (ids.length === 0) {
alert('{{ trans('global.datatables.zero_selected') }}')
return
}
if (confirm('{{ trans('global.areYouSure') }}')) {
$.ajax({
headers: {'x-csrf-token': _token},
method: 'POST',
url: config.url,
data: { ids: ids, _method: 'DELETE' }})
.done(function () { location.reload() })
}
}
}
dtButtons.push(deleteButton)
#endcan
$.extend(true, $.fn.dataTable.defaults, {
order: [[ 1, 'desc' ]],
pageLength: 25,
});
let options = {
"sScrollX": "100%",
"sScrollXInner": "110%",
"bScrollCollapse": true,
"colReorder": true,
};
$('#tabls').DataTable(options);
// {
// buttons: dtButtons,
// }),
$('a[data-toggle="tab"]').on('shown.bs.tab', function(e){
$($.fn.dataTable.tables(true)).DataTable()
.columns.adjust();
});
})
</script>
#endsection
Please advise me to solve this issue
Thank you for your time.

Please refer this one for datatable integration
https://github.com/yajra/laravel-datatables

Use server side datatables Install this
a working example from my side into controller
if ($request->ajax()) {
$timeZone = $request->timeZone;
$query = Order::query();
$data = $query->with('buyerOrders', 'sellerOrders', 'oderItems', 'teamMemberOrder')
->where('sellerId', Auth::id())
->where('status', OrderStatusEnum::COMPLETED)
->orderBy('createdAt', 'DESC')
->get();
return Datatables::of($data)
->addIndexColumn()
->addColumn('C_name', function ($row) {
return $row->buyerOrders->getFullNameAttribute();
})
->addColumn('teamMember', function ($order) {
if ($order->teamMemberId) {
return $order->teamMemberOrder->getFullNameAttribute();
} else {
return 'N/A';
}
})
->addColumn('price', function (Order $order) {
return $order->oderItems->map(function ($oderItem) {
return $oderItem->unitPrice * $oderItem->productQuantity;
})->sum();
})
->addColumn('isScheduled', function ($row) {
if ($row->isScheduled == 1) {
return '
<span class="badge badge-pill badge-info">Scheduled </span>
';
} else {
return '
<span class="badge badge-pill badge-success">Immediate</span>
';
}
})
->addColumn('booking', function ($row) {
return $row->id;
})
->addColumn('orderType', function ($row) {
if ($row->isDeliverable == 1) {
return '
<span class="badge badge-pill badge-info">Deliverable </span>
';
} else {
return '
<span class="badge badge-pill badge-success"> Non Deliverable</span>
';
}
})
->addColumn('orderPlace', function ($order) use ($timeZone) {
return Carbon::parse($order->updatedAt)->setTimezone($timeZone)->format('Y-m-d H:i:s');
})
->rawColumns(['isScheduled', 'orderType'])
->make(true);
}
return view("Store.order.completeOrder");
}

Related

Watch newValue, oldValue from Angular to Vue

Im converting a site from php and Angular to Vue Im pretty new to both but I'm 99% done. I need to watch when the data changes. its basically a league table and when some one goes up it css they go green when they go down css they go red. Ive tried converting the Angular function here
$scope.$watch(function () {
return $scope.scores;
},
function(newVal, oldVal) {
angular.forEach(newVal, function(value1, key1) {
angular.forEach(oldVal, function(value2, key2) {
if (value1.id === value2.id) {
if (key1 < key2) {
value1.posChang = 'up';
} else if (key1 > key2) {
value1.posChang = 'down';
}
}
});
});
}, true);
and convert to vue here
watch: {
scores: {
immediate: true,
handler (newValue, oldValue) {
console.log(newValue)
console.log(oldValue)
this.newValue.forEach(newValue, function (value1, key1) {
this.oldValue.forEach(oldValue, function (value2, key2) {
if (value1.id === value2.id) {
if (key1 < key2) {
value1.posChang = 'up';
} else if (key1 > key2) {
value1.posChang = 'down';
}
}
});
});
},
deep: true
}
},
it console prints both Old and New but it crashes when it hits the forEach
any help would be great
as requested the whole file :-
<template>
<div id="rScore">
<div class="title">
<h2>{{ data.full_name }} - {{ data.round_head }}</h2>
<br />
<p>
{{ data.course_dates }}
</p>
</div>
<table>
<thead>
<tr class="title" v-if="this.roundsPlayed > 1">
<th :class="cell">
Pos
</th>
<th :class="cell">
Player Name
</th>
<th :class="cell">
Nat.
</th>
<th :class="cell">
Par
</th>
<th
v-for="(i, roundIt) in range(1, roundsPlayed)"
:key="roundIt"
:class="cell"
>
R{{ i }}
</th>
<th :class="cell">
Score
</th>
</tr>
<tr v-else>
<th :class="cell">
Pos
</th>
<th :class="cell">
Player Name
</th>
<th :class="cell">
Nat.
</th>
<th :class="cell">
Par
</th>
<th :class="cell">
Score
</th>
</tr>
</thead>
<tbody v-if="this.roundsPlayed > 1">
<template v-for="(scores, index) in scores">
<tr #click.stop="rowClicked(index)" :key="index + Math.random()">
<td :class="cell">
{{ scores.pos }}
</td>
<td #click="playerCard" :title="scores.member_no" :class="cell">
{{ scores.name }}
</td>
<td :class="cell" :title="scores.nationality">
<span>
<img
:class="flag"
:src="
('https://assets.ocs-sport.com/flags/svg/flag_' +
scores.nationality)
| lowercase
"
/>
</span>
</td>
<td v-if="scores.vspar < 0" :class="[up, cell]">
{{ scores.vspar }}
</td>
<td v-else-if="scores.vspar > 0" :class="[down, cell]">
{{ scores.vspar }}
</td>
<td v-else :class="cell">
{{scores.vspar}}
</td>
<td :class="cell">
<span v-if="scores.vspar_R1 < 0" :class="[up, cell]">
{{ scores.score_R1 }}
</span>
<span v-else-if="scores.vspar_R1 > 0" :class="[down, cell]">
{{ scores.score_R1 }}
</span>
<span v-else :class="cell">
{{ scores.score_R1 }}
</span>
</td>
<td v-if="roundsPlayed > 1" :class="cell">
{{ scores.score_R2 }}
</td>
<td v-if="roundsPlayed > 2" :class="cell">
{{ scores.score_R3 }}
</td>
<td v-if="roundsPlayed > 3" :class="cell">
{{ scores.score_R4 }}
</td>
<td v-if="roundsPlayed > 4" :class="cell">
{{ scores.score_R5 }}
</td>
<td v-if="roundsPlayed > 5" :class="cell">
{{ scores.score_R6 }}
</td>
<td v-if="roundsPlayed > 6" :class="cell">
{{ scores.score_R7 }}
</td>
<td v-else :class="cell">
{{ scores.score }}
</td>
</tr>
<tr
#click.stop="rowClicked(rowClicked === -1)"
v-if="index === clickedRow"
class="tr-kids"
:key="index + Math.random()"
>
<b-row>
<b-col>
<table :class="tableRow">
<thead>
<tr class="titleReport">
<th :class="cellReport">
Hole
</th>
<th :class="cellReport">
1
</th>
<th :class="cellReport">
2
</th>
<th :class="cellReport">
3
</th>
<th :class="cellReport">
4
</th>
<th :class="cellReport">
5
</th>
<th :class="cellReport">
6
</th>
<th :class="cellReport">
7
</th>
<th :class="cellReport">
8
</th>
<th :class="cellReport">
9
</th>
<th :class="cellReport">
OUT
</th>
</tr>
</thead>
<tbody>
<tr class="titleReport">
<td :class="cellReport">
Yards
</td>
<td
:class="cellReport"
v-for="number in playerCardData.course_length_yards
.split(',')
.slice(0, 9)"
:key="number"
>
{{ number }}
</td>
<td :class="cellReport">
{{ playerCardData.course_out_length.slice(1, 6) }}
</td>
</tr>
<tr class="titleReport">
<td :class="cellReport">
Par
</td>
<td
:class="cellReport"
v-for="number in playerCardData.course_par
.split(',')
.slice(0, 9)"
:key="number"
>
{{ number }}
</td>
<td :class="cellReport">
{{ playerCardData.course_out_par.slice(1, 5) }}
</td>
</tr>
<tr
v-for="(i, roundIt1) in range(1, roundsPlayed)"
:key="roundIt1"
:class="cellReport"
>
<td>R{{ i }}</td>
<template v-if="i === 1">
<td
:class="cellReport"
v-for="scoreRound in playerCardData.score_R1
.split(',')
.slice(0, 10)"
:key="scoreRound"
>
<span>
{{ scoreRound }}
</span>
</td>
</template>
<template v-else-if="i === 2">
<td
:class="cellReport"
v-for="scoreRound in playerCardData.score_R2
.split(',')
.slice(0, 10)"
:key="scoreRound"
>
<span>
{{ scoreRound }}
</span>
</td>
</template>
<template v-else-if="i === 3">
<td
:class="cellReport"
v-for="scoreRound in playerCardData.score_R3
.split(',')
.slice(0, 10)"
:key="scoreRound"
>
<span>
{{ scoreRound }}
</span>
</td>
</template>
<template v-else-if="i === 4">
<td
:class="cellReport"
v-for="scoreRound in playerCardData.score_R4
.split(',')
.slice(0, 10)"
:key="scoreRound"
>
<span>
{{ scoreRound }}
</span>
</td>
</template>
<template v-else-if="i === 5">
<td
:class="cellReport"
v-for="scoreRound in playerCardData.score_R5
.split(',')
.slice(0, 10)"
:key="scoreRound"
>
<span>
{{ scoreRound }}
</span>
</td>
</template>
<template v-else-if="i === 6">
<td
:class="cellReport"
v-for="scoreRound in playerCardData.score_R6
.split(',')
.slice(0, 9)"
:key="scoreRound"
>
<span>
{{ scoreRound }}
</span>
</td>
</template>
<template v-else-if="i === 7">
<td
:class="cellReport"
v-for="scoreRound in playerCardData.score_R7
.split(',')
.slice(0, 9)"
:key="scoreRound"
>
<span>
{{ scoreRound }}
</span>
</td>
</template>
</tr>
</tbody>
</table>
</b-col>
<b-col>
<table :class="tableRow">
<thead>
<tr class="titleReport">
<th :class="cellReport">
10
</th>
<th :class="cellReport">
11
</th>
<th :class="cellReport">
12
</th>
<th :class="cellReport">
13
</th>
<th :class="cellReport">
14
</th>
<th :class="cellReport">
15
</th>
<th :class="cellReport">
16
</th>
<th :class="cellReport">
17
</th>
<th :class="cellReport">
18
</th>
<th :class="cellReport">
IN
</th>
<th :class="cellReport">
TOT
</th>
</tr>
</thead>
<tbody>
<tr class="titleReport">
<td
:class="cellReport"
v-for="number in playerCardData.course_length_yards
.split(',')
.slice(9, 18)"
:key="number"
>
{{ number }}
</td>
<td :class="cellReport">
{{ playerCardData.course_in_length.slice(1, 6) }}
</td>
<td :class="cellReport">
{{ playerCardData.course_total_length.slice(1, 6) }}
</td>
</tr>
<tr class="titleReport">
<td
:class="cellReport"
v-for="number in playerCardData.course_par
.split(',')
.slice(9, 18)"
:key="number"
>
{{ number }}
</td>
<td :class="cellReport">
{{ playerCardData.course_in_par.slice(1, 5) }}
</td>
<td :class="cellReport">
{{ playerCardData.course_total_par.slice(1, 5) }}
</td>
</tr>
<tr
v-for="(i, roundIt2) in range(1, roundsPlayed)"
:key="roundIt2"
:class="cellReport"
>
<template v-if="i === 1">
<td
:class="cellReport"
v-for="scoreRound in playerCardData.score_R1
.split(',')
.slice(10, 21)"
:key="scoreRound"
>
<span>
{{ scoreRound }}
</span>
</td>
</template>
<template v-else-if="i === 2">
<td
:class="cellReport"
v-for="scoreRound in playerCardData.score_R2
.split(',')
.slice(10, 21)"
:key="scoreRound"
>
<span>
{{ scoreRound }}
</span>
</td>
</template>
<template v-else-if="i === 3">
<td
:class="cellReport"
v-for="scoreRound in playerCardData.score_R3
.split(',')
.slice(10, 21)"
:key="scoreRound"
>
<span>
{{ scoreRound }}
</span>
</td>
</template>
<template v-else-if="i === 4">
<td
:class="cellReport"
v-for="scoreRound in playerCardData.score_R4
.split(',')
.slice(10, 21)"
:key="scoreRound"
>
<span>
{{ scoreRound }}
</span>
</td>
</template>
<template v-else-if="i === 5">
<td
:class="cellReport"
v-for="scoreRound in playerCardData.score_R5
.split(',')
.slice(10, 21)"
:key="scoreRound"
>
<span>
{{ scoreRound }}
</span>
</td>
</template>
<template v-else-if="i === 6">
<td
:class="cellReport"
v-for="scoreRound in playerCardData.score_R6
.split(',')
.slice(10, 21)"
:key="scoreRound"
>
<span>
{{ scoreRound }}
</span>
</td>
</template>
<template v-else-if="i === 7">
<td
:class="cellReport"
v-for="scoreRound in playerCardData.score_R7
.split(',')
.slice(10, 21)"
:key="scoreRound"
>
<span>
{{ scoreRound }}
</span>
</td>
</template>
</tr>
</tbody>
</table>
</b-col>
</b-row>
</tr>
</template>
</tbody>
<tbody v-else>
<tr v-for="(scores, index) in scores" :key="index">
<td :class="cell">
{{ scores.pos }}
</td>
<td :class="{ up: scores.posChang === 'up', down: scores.posChang === 'down' }" >
{{ scores.name }}
</td>
<td :class="cell" :title="scores.nationality">
<span>
<img
:class="flag"
:src="
('https://assets.ocs-sport.com/flags/svg/flag_' +
scores.nationality)
| lowercase
"
/>
</span>
</td>
<td v-if="scores.vspar < 0" :class="[cell, up]">
{{ scores.vspar }}
</td>
<td v-else-if="scores.vspar > 0" :class='[cell, down]'>
{{scores.vspar}}
</td>
<td v-else :class="cell">
{{scores.vspar}}
</td>
<td v-if="scores.vspar < 0" :class="[cell, up]">
{{ scores.score }}
</td>
<td v-else-if="scores.vspar > 0" :class='[cell, down]'>
{{scores.score}}
</td>
<td v-else :class="cell">
{{scores.score}}
</td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
import axios from "axios";
export default {
name: "rScore",
props: ["data", "home", "scores"],
data() {
return {
cell: "cell",
cellReport: "cellReport",
flag: "flag",
title: "title",
tableRow: "tableRow",
clickedRow: -1,
courseData: this.data,
cardID: [],
playerCardData: [],
id: this.$route.query.id,
code: this.$route.query.code,
up:'up',
down:'down'
};
},
methods: {
range: function(start, end) {
if (this.roundsPlayed === 1) return this.roundsPlayed;
else
return Array(end - start + 1)
.fill()
.map((_, idx) => start + idx);
},
rowClicked: function(index) {
this.clickedRow = index;
},
playerCard: function(event) {
var cardID = event.target.getAttribute("title");
return (
(this.cardID = cardID),
axios
.get(
" url" +
this.id +
"/" +
this.id +
"-" +
this.code +
"-cards-" +
this.cardID +
".json?randomadd=1613462964358"
)
.then((response) => (this.playerCardData = response.data))
);
},
},
watch: {
scores: {
immediate: true,
handler (newValue, oldValue) {
console.log(newValue)
console.log(oldValue)
newValue.forEach(newValue, function (value1, key1) {
oldValue.forEach(oldValue, function (value2, key2) {
if (value1.id === value2.id) {
if (key1 < key2) {
value1.posChang = 'up';
} else if (key1 > key2) {
value1.posChang = 'down';
}
}
});
});
},
deep: true
}
},
computed: {
roundsPlayed() {
return this.data.rounds_played;
},
},
filters: {
lowercase: function(value) {
if (!value) {
return "";
}
return value.toLowerCase() + ".svg";
},
},
};
</script>
<style scoped>
.cell {
width: 10%;
text-align: center;
}
.cellReport {
width: 10%;
text-align: center;
}
.tableRow {
width: 100%;
}
.flag {
width: 7%;
}
.row {
padding-top: 10%;
padding-bottom: 10%;
width: 405%;
padding-left: 20%;
background-color: white;
}
.col {
padding-left: 0;
padding-right: 0;
}
.title {
text-align: center;
background-color: #263056;
color: white;
}
.titleReport {
background-color: #1b509b !important;
color: white;
}
tr:nth-child(even) {
background-color: #f2f2f2;
}
.up{
color: #A52A2A;
}
.down{
color: #1E90FF;
}
</style>
Remove this. from newValue and oldValue
Took Mi-Creativity code pen above and modified as it was making everyone the same
this now works perfect. thanks for the help
watch: {
score: {
immediate: true,
handler(newValue, oldValue) {
newValue.forEach((value1, key1) => {
oldValue.forEach((value2, key2) => {
if (value1.id === value2.id) {
if(key1 < key2){
value1.posChang = 'up';
} else if (key1 > key2) {
value1.posChang = 'down';
}
}
});
});
console.log(newValue);
},
deep: true,
},
},

Custom filter angular on ng-repeat for stike text if disabled

I'd like to add a custom filter on my angularJS app. I want di strike text like this way if the object in the ng-repat has the isDeleted flag set as true. Code: here the HTML:
<table id="tableText" class="table table-hover table-striped" ng-init="allNews()">
<tr>
<th>Titolo</th>
<th>Text</th>
<th>Disattivato</th>
<th>Modifica</th>
<th ng-if="!cancelDelete">Elimina</th>
<th ng-if="cancelDelete">Annulla</th>
</tr>
<tr ng-repeat="news in allNews | filter: deleteTitleText(news)">
<td>
<div ng-hide="editingData[news.id]">{{ news.title }}</div>
<div ng-show="editingData[news.id]"><input type="text" class="form-control" ng-model="news.title" /></div>
</td>
<td>
<div ng-hide="editingData[news.id]">{{ news.arg }}</div>
<div ng-show="editingData[news.id]"><input type="text" class="form-control" ng-model="news.arg" /></div>
</td>
<td>
<div ng-hide="editingData[news.id]"><input type="checkbox" disabled ng-model="news.isDeleted"></div>
<div ng-show="editingData[news.id]"><input type="checkbox" ng-model="news.isDeleted"></div>
</td>
<td>
<div ng-hide="editingData[news.id]"><button id="modify" class="btn btn-primary" ng-click="modify(news, $event)">Modifica</button></div>
<div ng-show="editingData[news.id]"><button id="accept" class="btn btn-success" ng-click="update(news)">Accetta</button></div>
</td>
<td>
<div ng-hide="editingData[news.id]"><button id="delete" class="btn btn-danger" ng-click="delete(news.id)">Cancella</button></div>
<div ng-show="editingData[news.id]"><button id="cancel" class="btn btn-danger" ng-click="cancelModify()">Annulla</button></div>
</td>
</tr>
</table>
The JS:
app.filter('deleteTitleText', function () {
return function (news) {
if (news.isDeleted == true) {
news.title = "<span><del>" + news.title + "</del></span>";
news.arg = "<span><del>" + news.arg + "</del></span>";
}
return news;
}
});
This is a good way to implement this kind of filter? For now I receive this error: angular.js:13920 Error: [filter:notarray] Expected array but received: function (). Thanks
OPTION 1:
<table id="tableText" class="table table-hover table-striped" ng-init="allNews()">
<tr>
<th>Titolo</th>
<th>Text</th>
<th>Disattivato</th>
<th>Modifica</th>
<th ng-if="!cancelDelete">Elimina</th>
<th ng-if="cancelDelete">Annulla</th>
</tr>
<tr ng-repeat="news in allNews">
<td>
<div ng-hide="editingData[news.id]">
<span ng-hide="news.isDeleted">{{ news.title }}</span>
<span ng-show="news.isDeleted"><del>{{ news.title }}</del></span>
<!-- USING ng-if -->
<!--
<span ng-if="!news.isDeleted">{{ news.title }}</span>
<span ng-if="news.isDeleted"><del>{{ news.title }}</del></span>
-->
</div>
<div ng-show="editingData[news.id]"><input type="text" class="form-control" ng-model="news.title" /></div>
</td>
<td>
<div ng-hide="editingData[news.id]">
<span ng-hide="news.isDeleted">{{ news.arg }}</span>
<span ng-show="news.isDeleted"><del>{{ news.arg }}</del></span>
<!-- USING ng-if -->
<!--
<span ng-if="!news.isDeleted">{{ news.arg }}</span>
<span ng-if="news.isDeleted"><del>{{ news.arg }}</del></span>
-->
</div>
<div ng-show="editingData[news.id]"><input type="text" class="form-control" ng-model="news.arg" /></div>
</td>
<td>
<div ng-hide="editingData[news.id]"><input type="checkbox" disabled ng-model="news.isDeleted"></div>
<div ng-show="editingData[news.id]"><input type="checkbox" ng-model="news.isDeleted"></div>
</td>
<td>
<div ng-hide="editingData[news.id]"><button id="modify" class="btn btn-primary" ng-click="modify(news, $event)">Modifica</button></div>
<div ng-show="editingData[news.id]"><button id="accept" class="btn btn-success" ng-click="update(news)">Accetta</button></div>
</td>
<td>
<div ng-hide="editingData[news.id]"><button id="delete" class="btn btn-danger" ng-click="delete(news.id)">Cancella</button></div>
<div ng-show="editingData[news.id]"><button id="cancel" class="btn btn-danger" ng-click="cancelModify()">Annulla</button></div>
</td>
</tr>
</table>
OPTION 2:
<span ng-bind-html="news | deleteTitleText"></span>
app.filter('deleteTitleText', function ($sce) {
return function (input) {
if(input.isDeleted) {
output = $sce.trustAsHtml("<del>"+input.title+"</del>");
} else {
output = $sce.trustAsHtml("<span>"+input.title+"</span>");
}
return output;
};
});
remove filter from ng-repeat <tr ng-repeat="news in allNews">
So final would be similar to :
<tr ng-repeat="news in allNews">
<td>
<div ng-hide="editingData[news.id]">
<span ng-bind-html="news | deleteTitleText"></span>
</div>
<div ng-show="editingData[news.id]"><input type="text" class="form-control" ng-model="news.title" /></div>
</td>
....
....
Hope this helps
You need to alter you filter to expect the entire allNews array/object and work with that instead of just a single item in the list.
This might help.
For instance:
app.filter('deleteTitleText', function () {
return function (allNews) {
var filtered = [];
angular.forEach(allNews, function(news) {
if (news.isDeleted == true) {
news.title = "<span><del>" + news.title + "</del></span>";
news.arg = "<span><del>" + news.arg + "</del></span>";
}
filtered.push(news);
});
return filtered;
}
});
Your ng-repeat should be changed from:
ng-repeat="news in allNews | filter: deleteTitleText(news)"
To:
ng-repeat="news in allNews | deleteTitleText"
Try to use ng-style, like in this plunker: https://plnkr.co/edit/0koMSQ54gUChdpB4Vrrm?p=preview
!item.isDisabled ? {'text-decoration': 'line-through'} : {'text-decoration': 'none'}
You can simply use ng-show and ng-hide
<tr ng-repeat="news in allNews">
<span ng-show="news.isDeleted"><del>{{news.title}}</del></span>
<span ng-show="news.isDeleted"><del>{{news.arg}}</del></span>
<span ng-hide="news.isDeleted"><del>{{news.title}}</del></span>
<span ng-hide="news.isDeleted"><del>{{news.arg}}</del></span>
.
.
.
</tr>

Uncaught TypeError: Cannot read property 'file' of undefined(…)

I am trying to upload an image from my html an on click of save button, i am calling an upload function in the controller. When i enter the upload function in controller, i am not able to access $scope to check the $scope.file.name.
//upload image.html
<div class="horizontal">
<table border=1 frame=void rules=rows class="ui celled table" >
<thead style="text-align: center;">
<tr>
<th> Id </th>
<th> Question </th>
<th> Option A </th>
<th> Option B </th>
<th> Option C </th>
<th> Option D </th>
<th> Answer </th>
<th> Section id </th>
<th> Image </th>
<th> Edit</th>
</tr></thead>
<tbody ng-repeat="ques in questionObj | filter: searchText" style="text-align: center;">
<tr>
<td>{{$index + 1}}</td>
<td><span ng-show="editEnabled" ng-model="Title">
{{ ques.Title || 'empty' }}
</span>
<div ng-hide="editEnabled">
<textarea ng-model="ques.Title"></textarea>
</div>
</td>
<td><span ng-show="editEnabled" ng-model="Title">{{ques.Option_a || 'empty'}} </span>
<div ng-hide="editEnabled" class="option">
<textarea ng-model="ques.Option_a"></textarea>
</div>
</td>
<td><span ng-show="editEnabled" ng-model="Title">{{ques.Option_b || 'empty'}} </span>
<div ng-hide="editEnabled" class="option">
<textarea ng-model="ques.Option_b"></textarea>
</div>
</td>
<td><span ng-show="editEnabled" ng-model="Title">{{ques.Option_c || 'empty'}} </span>
<div ng-hide="editEnabled" class="option">
<textarea ng-model="ques.Option_c"></textarea>
</div>
</td>
<td><span ng-show="editEnabled" ng-model="Title">{{ques.Option_d || 'empty'}} </span>
<div ng-hide="editEnabled" class="option">
<textarea ng-model="ques.Option_d"></textarea>
</div>
</td>
<td><span ng-show="editEnabled" ng-model="Title">{{ques.Answer || 'empty'}} </span>
<div ng-hide="editEnabled" class="option">
<textarea ng-model="ques.Answer"></textarea>
</div>
</td>
<td><span ng-show="editEnabled" ng-model="Title">{{ques.Section_id || 'empty'}} </span>
<div ng-hide="editEnabled" class="option">
<input type="text" ng-model="ques.Section_id"></input>
</div>
</td>
<td>
<span ng-if="ques.Image != 'nil'" ng-show="editEnabled" ng-model="Title"> <img ng-src="{{ques.Image}}" class="image-container" /></span>
<span ng-if="ques.Image === 'nil'" ng-show="editEnabled" ng-model="Title">No Image</span>
<div ng-if="ques.Image != 'nil'" ng-hide="editEnabled" class="option">
<img ng-src="{{ques.Image}} " class="image-container" />
</div>
<div ng-if="ques.Image === 'nil'" ng-hide="editEnabled" class="option">
<input class="bottom-marg-15" type="file" name="file" file onchange="angular.element(this).scope().imageLoad(this)"></input>
<!-- Progress Bar -->
<div class="progress">
<div class="progress-bar" role="progressbar" aria-valuenow="{{ uploadProgress }}" aria-valuemin="0" aria-valuemax="100" style="width: {{ uploadProgress }}%;">
{{ uploadProgress == 0 ? '' : uploadProgress + '%' }}
</div>
</div>
<div ng-repeat="step in stepsModel">
<img class="small-thumb" ng-src="{{step}}" />
</div>
</div>
</td>
<td style="white-space: nowrap">
<div class="buttons" ng-show="editEnabled" ng-show="editEnabled">
<button class="btn btn-primary" ng-click="editEnabled = !editEnabled">edit</button>
<button class="btn btn-danger" ng-click="question.removeUser($index,ques.Id)">del</button>
</div>
<div ng-hide="editEnabled" class="form-buttons form-inline">
<button ng-model="Title" ng-disabled="editQuestionForm.$waiting" ng-click=" upload(); editEnabled = !editEnabled" class="btn btn-primary">
save
</button>
<button type="button" ng-click="editEnabled = !editEnabled" class="btn btn-default">
cancel
</button>
</div>
</td>
</tr>
</tbody>
this is the controller which has the upload function. I am not able to access $scope inside upload function.
'use strict';
angular.module('onlineTestAngularApp')
.controller('editQuestionCtrl', function($scope, GetQuestionsService, $window, $location, localStorageService, ENV) {
var vm = this;
vm.success = false;
vm.auth_token = localStorageService.get('rec-auth-token');
vm.role = localStorageService.get('role');
$scope.editEnabled = true;
$scope.access_key = ENV.access_key;
$scope.secret_key = ENV.secret_key;
$scope.bucket = "q-auth/angular_test/";
$scope.stepsModel = [];
$scope.imageLoad = function(element){
var reader = new FileReader();
reader.onload = $scope.imageIsLoaded;
reader.readAsDataURL(element.files[0]);
}
$scope.imageIsLoaded = function(e){
$scope.$apply(function() {
$scope.stepsModel.push(e.target.result);
});
}
$scope.upload = function($scope){
console.log("inside upload");
}
});
Your upload() is having a parameter called $scope, remove it.
Change:
$scope.upload = function($scope){
console.log("inside upload");
}
To:
$scope.upload = function(){
console.log("inside upload");
};
Because when you call the function upload() it will expect to pass an argument, $scope in the function is taken as local variable of that function, hence becoming undefined.
Once you enter the controller's function you have access to its $scope. There's no need to pass it as a parameter:
Controller
$scope.upload = function() {
console.log($scope.stepsModel) // or any other property
}
It seems you mix two techniques for accessing controller's scope: vm and $scope. My advice is to use vm only for exposing the controller variables to the view. Using $scope will soon be deprecated and I use it mainly for $watching changes in the view.

filters stopped working ..shows blank page

When I click my headers, it does not sort and the table disappears
angular.module('maniaApp')
.controller('EventCtrl', function ($scope,$location,$http) {
$scope.sortType = '_source.event_name'; // set the default sort type
$scope.sortReverse = false; // set the default sort order
$scope.searchEvent = ''; // set the default search/filter term
var url = "http://api.loc/events/get-events";
$http.get(url).success(function api(data, status, headers, config){
$scope.events = data;
}).error(function api(data, status, headers, config){
console.error(data, status, headers, config);
});
here is my html
<div class="container">
<!--<div ng-view=""></div>-->
<div ng-controller="EventCtrl">
<div class="alert alert-info">
<p>Sort Type: {{ sortType }}</p>
<p>Sort Reverse: {{ sortReverse }}</p>
<p>Search Query: {{ searchEvent }}</p>
</div>
<form>
<div class="form-group">
<div class="input-group">
<div class="input-group-addon"><i class="fa fa-search"></i></div>
<input type="text" class="form-control" placeholder="Search events" ng-model="searchEvent">
</div>
</div>
</form>
<table class="table table-bordered table-striped">
<thead>
<tr>
<td>
<a href="#" ng-click="sortType = '_source.id'; sortReverse = !sortReverse">
Id
<span ng-show="sortType == '_source.id';" class="fa fa-caret-down"></span>
</a>
</td>
<td>
<a href="#" ng-click="sortType = '_source.event_name'; sortReverse = !sortReverse">
<span ng-show="sortType == '_source.event_name';" class="fa fa-caret-down"></span>
Event Name
</a>
</td>
<td>
<a href="#" ng-click="sortType = '_source.event_status_id'; sortReverse = !sortReverse">
<span ng-show="sortType == '_source.event_sid'" class="fa fa-caret-down"></span>
Event Status
</a>
</td>
</tr>
</thead>
<tbody>
<tr ng-repeat="event in events | orderBy:sortType:sortReverse | filter:searchEvent">
<td>{{ event._source.event_id }}</td>
<td>{{ event._source.event_name }}</td>
<td>{{ event._source.event_sid }}</td>
</tr>
</tbody>
</table>
</div>
</div>

Angular overlay (spinner) when we have multiple request

I have below HTML panel and binds to the controller, in the controller I have 4 calls to server to get my data, my question is how can I show spinner or overlay on top of this panel until all the requests to the server are resolved and I can show the data smoothly.
<div class="container-fluid margin10 padding10 myPanel">
<div class="row-fluid name" ng-bind-html="viewData.msg.name"></div>
<div class="row">
<div class="col-md-11">
<div ng-bind-html="'• ' + (viewData.msg.filtersStr | limitTo: 140) + (viewData.msg.filtersStr.length > 140 ? '...' : '')" ng-attr-title="{{viewData.msg.filtersTooltipStr}}"></div>
</div>
</div>
<div class="row top-buffer-margin">
<div class="col-md-4 text-right">
<div class="col-md-8"><span class="font10" translate="msgs.details.confidence"></span>:</div>
<span ng-bind-html="viewData.msg.severity" ng-class="viewData.msg.severityColor" class="font10 col-md-4 confidence-span"></span>
</div>
</div>
<hr>
<table class="table-striped col-md-12 top-buffer-margin">
<thead>
<tr>
<th class="col-md-3"></th>
<th class="col-md-2 text-center" ng-bind-html="'<i>' + ('msgs.details.countColHead' | translate) + '<i>'"></th>
<th class="col-md-4 text-center" ng-bind-html="'<i>' + ('msgs.details.dynamicCalculation' | translate) + '<i>'"></th>
<th class="col-md-3 text-right" ng-bind-html="'<i>' + ('msgs.details.CalculationColHead' | translate) + '<i>'"></th>
</tr>
</thead>
<tbody>
<tr class="">
<td class="col-md-3">
<div><span translate="msgs.details.number1"></span></div>
</td>
<td class="col-md-2 text-center">
<span ng-bind="viewData.msg.number1.dynamicCount "></span>
</td>
<td class="col-md-4 text-center" >
<span ng-bind="viewData.msg.number1.dynamicCalculation "></span>
</td>
<td class="col-md-3 text-right"
ng-bind="(viewData.msg.number1.percentageCalculation > 0 ? '+' : '') + viewData.msg.number1.percentageCalculation + '%'">
</td>
</tr>
<tr class="">
<td class="col-md-3">
<div><span translate="msgs.details.number2"></span></div>
</td>
<td class="col-md-2 text-center">
<span ng-bind="viewData.msg.number2.dynamicCount "></span>
</td>
<td class="col-md-4 text-center">
<span ng-bind="viewData.msg.number2.dynamicCalculation "></span>
</td>
<td class="col-md-3 text-right"
ng-bind="(viewData.msg.number2.percentageCalculation > 0 ? '+' : '') + viewData.msg.number2.percentageCalculation + '%'">
</td>
</tr>
<tr class="">
<td class="col-md-3">
<div><span translate="msgs.details.number3"></span></div>
</td>
<td class="col-md-2 text-center">
<span ng-bind="viewData.msg.number3.dynamicCount "></span>
</td>
<td class="col-md-4 text-center">
<span ng-bind="viewData.msg.number3.dynamicCalculation "></span>
</td>
<td class="col-md-3 text-right"
ng-bind="(viewata.msg.number3.percentageCalculation > 0 ? '+' : '') + viewData.msg.number3.percentageCalculation + '%'">
</td>
</tr>
</tbody>
</table>
</div>
The controller is like this:
(function() {
'use strict';
angular.module('myApp')
.controller('myController', myController);
/** #ngInject */
function myController($scope, BinsResource, msgEvents, appConstants) {
var msg = null;
$scope.viewData = {msg: {}};
var init = function() {
}
var getMsgDetails = function() {
msg = $scope.selectedMsg;
//
$scope.viewData.msg = {
ruleName: msg.ruleName,
date: moment.utc(msg.time).format('YYYY-MM-DD'),
time: moment.utc(msg.time).format('HH:mm'),
severity: msg.severity,
severityColor: msgsService.getSeverityClassColor(msg.severity, appConstants),
number1: buildEventsData(msg, appConstants.measureType.number1),
number2: buildEventsData(msg, appConstants.measureType.number2),
number3: buildEventsData(msg, appConstants.measureType.number3)
};
var params = prepareDataForBinsHttp(msg);
//number1
BinsResource.post('number1', params).then(
function(response) {
var calculationObject = calculateCalculation(response.data.Interval, msg);
$scope.viewData.msg.number1.dynamicCalculation = calculationObject.calculation;
$scope.viewData.msg.number1.dynamicCount = calculationObject.count;
},
function(error) {
//TODO : Display callback error
}
);
//number2
BinsResource.post('number2', params).then(
function(response) {
var calculationObject = calculateCalculation(response.data.Interval, msg);
$scope.viewData.msg.number2.dynamicCalculation = calculationObject.calculation;
$scope.viewData.msg.number2.dynamicCount = calculationObject.count;
},
function(error) {
//TODO : Display callback error
}
);
//number3
BinsResource.post('number3', params).then(
function(response) {
var calculationObject = calculateCalculation(response.data.Interval, msg);
$scope.viewData.msg.number3.dynamicCalculation = calculationObject.calculation;
$scope.viewData.msg.number3.dynamicCount = calculationObject.count;
},
function(error) {
//TODO : Display callback error
}
);
}
//
$scope.subscribe(msgEvents.message._ALERT_ITEM_SELECTED_, function(selectedMsg){
$scope.selectedMsg = selectedMsg;
if(selectedMsg != null){
getMsgDetails();
}
});
init();
};
})();
I want my HTML be blocked until getMsgDetails() does all its calls to server and calculation and was ready to populate the HTML, how can I do this?
I think your best option, is to use the following angular library
https://github.com/McNull/angular-block-ui
It will display a spinner, or a loading message, until all the promises are solved (it is configurable as well)
Demo here:
http://angular-block-ui.nullest.com/#!/

Resources