Angular : how to display a modal-dialog (chart) in ng-template - css

My application uses Angular 8 with Bootstrap and chart.js. I trying to render a bootstrap popup in an Angular ng-template directive. The popup (graph) is shown as soon as the user clicks in the last column in a table row. But as you can see on the picture, there is a white background, half the size of the actual graph. How can I get rid of this backgound ?
html part
<tbody>
<tr *ngFor="let stock of stockList; index as i" (click)="displaySelected(stock);">
<td style="width: 30px" scope="row">{{ i + 1 }}</td>
<td style="width: 40px">{{ stock.id }}</td>
<td style="width: 70px">{{ stock.symbol }}</td>
<td style="width: 70px">{{ stock.isin }}</td>
<td style="width: 180px">{{ stock.name }}</td>
<td style="width: 40px">{{ stock.liquid }}</td>
<td [class]="getFlagClass(stock.countryCode)" style="width: 14px"></td>
<td style="width: 180px">{{ stock.exchangeName }}</td>
<td style="width: 180px">{{ stock.sector }}</td>
<td style="width: 50px">{{ stock.active }}</td>
<td style="width: 30px"><img src="assets/img/chart.png" height="30" width="30" (click)="displayChart(content, stock);"/></td>
</tr>
</tbody>
</table>
</div>
<ng-template #content let-modal>
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">[name]</h5>
<button type="button" class="close" aria-label="Close" (click)="modal.dismiss('Cross click')">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<canvas id="myChart" width="1000" height="500"></canvas>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-outline-dark" (click)="modal.close('Save click')">any action</button>
</div>
</div>
</div>
</ng-template>
Component part
displayChart(content, stock: Istock) {
// Open popup window
this.modalService.open(content, {ariaLabelledBy: 'modal-basic-title'}).result.then((result) => {
this.closeResult = `Closed with: ${result}`;
}, (reason) => {
this.closeResult = `Dismissed ${this.getDismissReason(reason)}`;
});
const today = new Date();
const dd = today.getDate();
const mm = today.getMonth();
const yyyy = today.getFullYear();
const dateTo: Date = new Date(yyyy, mm, dd);
const dateFrom: Date = new Date(yyyy - 1, mm, dd);
// retrieve dates and Prices
this.labelsDate = new Array();
this.dataPrices = new Array();
this.http.post(this.apiUrl + '/instrument/getPrices', {id: stock.id, from: dateFrom, to: dateTo } ).subscribe( (result: IinstrumentPrice[]) => {
result.forEach(x => {
this.labelsDate.push(x.date);
this.dataPrices.push(x.close);
});
this.canvas = document.getElementById('myChart');
this.ctx = this.canvas.getContext('2d');
// display chart
const myChart = new Chart(this.ctx, {
type: 'line',
data: {
labels: this.labelsDate,
datasets: [{
label: 'Daily prices',
data: this.dataPrices,
fill: false,
borderWidth: 2,
borderColor: 'black'
}]
},
options: {
elements: { point: { radius: 0 } },
responsive: false,
display: true
}
});
});
}
css part
.row-input {
font-size: 15px;
padding-top: 2px;
padding-right: 1px;
padding-bottom: 1px;
padding-left: 2px;
}
input {
font-size: 15px;
}
.flag-us {
background-size:contain;
background-position:50%;
background-repeat:no-repeat;
position:relative;
display:inline-block;
width:1.33333333em;
line-height:1em;
background-image:url(../../assets/img/flags/united-states-of-america.png);
}
.modal-dialog{
position: relative;
display: table; /* This is important */
overflow-y: auto;
overflow-x: auto;
width: auto;
min-width: 300px;
}

The solution is to set a parameter {"size: 'xl'} in the open method.
displayChart(content, stock: Istock) {
// Open popup window
this.modalService.open(content, {size: 'xl'}).result.then((result) => {
and the html is also changed
<ng-template #content let-modal>
<div class="modal-header">
<div class="row">
<div class="col-sm-6">
<h4 class="modal-title">{{instrumentName}}</h4>
</div>
<div class="col-sm-8">
<div>last trading day : {{lastTradingDay}}</div>
</div>
</div>
<button type="button" class="close" aria-label="Close" (click)="modal.dismiss('Cross click')">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<canvas id="myChart" width="1000" height="500"></canvas>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-light" (click)="modal.close('Close click')">Close</button>
</div>
</ng-template>

Related

Navigation via button click in Angular 10

I have a list of names that I want to show only 5 of them on every page. Users can see the next 5 names by pressing “Next” button.
How can I set the click attribute of a button to do this for me in Angular.
Here is my .html file:
<div class="container">
<table class="table" >
<tbody *ngFor="let name of names.slice(index, index+ 5)">
<tr> <td>{{ name.value}} </td> </tr>
</tbody>
</table>
<button type="button" class="btn btn-primary" style ="float: left" (click)="previousFunction()"> < Previous </button>
<button type="button" class="btn btn-primary" style ="float: right" (click)="nextFunction()"> Next > </button>
</div>
Thanks in advance.
Well it was quiet easy to solve ...
Here is the html code:
<div class="container">
<table class="table" >
<tbody *ngFor="let name of names.slice(index, index+ 5)">
<tr> <td>{{ name.value}} </td> </tr>
</tbody>
</table>
<button type="button" class="btn btn-primary" style ="float: left" (click)="previousFunction($event, index)"> < Previous </button>
<button type="button" class="btn btn-primary" style ="float: right" (click)="nextFunction($event, index)"> Next > </button>
</div>
and here is the .ts code:
export class AppComponent {
constructor() { }
index: number = 0;
pageSize: number = 5;
names = [
{ name: 'a'},
{ name: 'b'},
{ name: 'c'},
{ name: 'd'},
{ name: 'e'},
{ name: 'f'},
{ name: 'g'},
{ name: 'h'},
{ name: 'i'},
{ name: 'j' },
];
previousFunction($event: any, count: any){
this.index = count - this.pageSize
}
nextFunction($event: any, count: any){
this.index = count + this.pageSize
}

How to display buttons as inline/block elements when one button is wrapped into a form?

How to display two buttons as block elements on small screens as well as inline elements on larger screens, when one of the buttons is wrapped inside a form?
I have two buttons, one is only a local link, the other one is wrapped (by my colleague) inside a from. Now I'm getting problems when displaying the page on smaller screens. The button inside the form will not appear as a block element anymore.
Result should look like this:
Small screen:
| button1 |
| button2 |
Large screen:
| button1 | | button2 |
My code so far:
https://www.bootply.com/CETPAyWp2K
(resize screen width to see the effect)
You need to update your styles to make the button take full space in mobile view.
Try using the following styles, that should work:
form { display: block; }
form button {
width:100%;
}
#media (min-width: 992px) {
form {
display: inline;
}
form button {
width: auto;
}
}
Use w-100 to button[type="submit"]
and in media-query of lg screen use:
#media (min-width: 992px) {
form {
display: inline;
}
button[type="submit"]{
width: auto!important;
}
}
See fiddle:https://jsfiddle.net/m9n4dgw7/5/
form { display: block;
}
#media (min-width: 992px) {
form {
display: inline;
}
button[type="submit"]{
width: auto!important;
}
}
<table class="table table-bordered">
<thead>
<tr>
<th scope="col">Name</th>
<th scope="col" class="text-right">Action</th>
</tr>
</thead>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.0/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.0/js/bootstrap.min.js"></script>
<tbody>
<tr>
<td class="content_name">Samplecol 1</td>
<td class="text-right">
<a class="btn btn-warning btn-sm btn-edit d-block d-lg-inline mb-1 mb-lg-0" href="#">Edit</a>
<form action="http://localhost:10777/Delete/3aac236e" method="post">
<button type="submit" class="btn btn-danger btn-sm w-100 d-block d-lg-inline mb-1 mb-lg-0">Delete</button>
</form>
</td>
</tr>
<tr>
<td class="content_name">Samplecol 2</td>
<td class="text-right">
<a class="btn btn-warning btn-sm btn-edit d-block d-lg-inline mb-1 mb-lg-0" href="#">Edit</a>
<form action="http://localhost:10777/Delete/d81de31b" method="post">
<button type="submit" class="btn btn-danger btn-sm w-100 d-block d-lg-inline mb-1 mb-lg-0">Delete</button>
</form>
</td>
</tr>
</tbody>
</table>
You can use Bootstrap and his grid to do responsive buttons.
For example you can use it as follow :
<td class="text-right">
<a class="btn btn-warning btn-sm col-md-3 col-sm-12 mb-1 mb-lg-0" href="#">Edit</a>
<form action="http://localhost:10777/Delete/3aac236e" method="post">
<button class="btn btn-danger btn-sm d-block d-lg-inline col-md-3 col-sm-12 mb-1 mb-lg-0" type="submit">Delete</button>
</form>
</td>
In this example buttons use full width on small devices and 1/4 width on other devices.

VueJS data bind related

I use vueJS to display a table data,when I click the delete button, the table always delete the last row,rather not a specific row.I use my custom UIComponent 'lovTable',it changes a input element to another style,how to avoid it and make the data and page change the same way.Here's the code.Tks.
<script>
//服务类型下拉列表数据转化
var mServiceTypeData = $.map(serviceTypeData, function (obj) {
obj.id = obj.value;
obj.text = obj.meaning;
return obj;
});
$(function(){
var vm = new Vue({
el: '#div-rms-memo',
data: {
sub:[]
},
methods:{
//添加子项目
addSubProject:function () {
vm.sub.push({
subPrjServeType:'',
subPrjBelongToDept:'',
});
},
//移除当前行的子项目
removeCurrentRow:function(index){
var $del=vm.sub.splice(index,1);
},
}
});
function renderLines(el, lineIndex){
//渲染select2
$("#subPro"+lineIndex).find(".subPrjServeType").select2Ext({
placeholder: '请选择服务类型',
data: mServiceTypeData,
width:150
}).on('change', function () {
vm.sub[lineIndex].subPrjServeType = $(this).val();
});
//归属部门LOV
$("#subPro"+lineIndex).find(".subPrjBelongToDept").lovTable({
title:'归属部门',
placeholder:'请选择',
valueField:'unitId',
textField:'unitName',
query:[
{
text:'部门ID',
name:'unitId'
},
{
text:'部门名称',
name:'unitName'
}
],
rowSelected:function(row){
vm.sub[lineIndex].subPrjBelongToDept=row.unitId;
},
textClear:function(){
vm.sub[lineIndex].subPrjBelongToDept = "";
}
},{
url : '${base.contextPath}/project/prjBranchView/queryConditionPage?'+_header+'='+_token,
columns: [{
title:'部门ID',
field:'unitId'
},{
title:'部门名称',
field:'unitName'
}]
});
}
Vue.directive('line-bind', {
bind: function (el, binding) {
var lineIndex = binding.value;
console.info('binding index='+lineIndex)
vm.$nextTick(function () {
renderLines(el,lineIndex);
})
},
unbind:function(el,binding){
vm.$nextTick(function () {
for(var i=0;i<vm.sub.length;i++){
renderLines(vm.sub[i],i);
}
})
}
});
})
</script>
<div class="content-wrapper">
<section class="content">
<div id="div-rms-memo" >
<div class="box box-blue">
<div class="form-group">
<a href="javascript:void(0)" class="btn btn-crm" v-on:click="addSubProject">
<span class="glyphicon glyphicon-plus">添加</span>
</a>
</div>
<table align="center" class="table table-bordered" v-line-bind="index" v-for="(el,index) in sub" :id="'subPro'+index" :cindex="index">
<tr class="crm-title">
<td align="center" valign="middle" rowspan="2" style="width:5%;">
<a href="javascript:void(0)" class="btn btn-default btn-xs removeSubPrj" id="removeSubPrjBtn" v-on:click="removeCurrentRow(index)">
<span class="glyphicon glyphicon-minus"></span>
</a>
</td>
<td align="center" style="width:15%;"class="required">服务类型</td>
<td align="center" style="width:15%;"class="required">归属部门</td>
<td align="center" style="width:15%;" class="required">人天</td>
</tr>
<tr>
<td align="center">
<input type="text" id="subPrjServeType" v-model="el.subPrjServeType" class="form-control input-sm subPrjServeType"/>
</td>
<td align="center">
<input type="text" class="form-control input-sm subPrjBelongToDept" v-model="el.subPrjBelongToDept">
</td>
<td align="center">
<input type="number" class="form-control input-sm subPrjPeoplePerDay" v-model="el.subPrjPeoplePerDay">
</td>
</tr>
</table>
</div>
</div>
</section>
</div>

How do you fix bootstrap table sizing when record result blows it out

I have a bootstrap table which is populated by an MVC loop of a model. However when my model renders a large number of records, it causes the table and panel the table is nested in stretch out too much in height. Is there a recommended way of making the table result scrollable when the records returned would exceed the max-height property of the table? A scrollable solution would be optimal.
Styles
.table{
width:100%;
}
thead,tbody,tr,td,th{
display:grid;
}
tr:after{
content: ' ';
display: block;
visibility:hidden;
clear:both;
}
thead th{
height: 30px;
}
tbody {
height: 120px;
overflow-y:auto;
}
thead {
}
tbody td. thead th {
width: 40.2%;
float: left;
}
Code below: (loop displays 34 records)
<div class="panel panel-primary">
<div class="panel-heading clearfix">
<h4 class="panel-title pull-left" style="padding-top: 7.5px;">My Team</h4>
<div class="btn-group pull-right">
<!--- Search bar-->
<form class="navbar-form navbar-right" role="search">
<div class="input-group">
<input type="text" class="form-control" placeholder="Search My Team">
<span class="input-group-btn">
<button type="submit" class="btn btn-default">
<span class="glyphicon glyphicon-search"></span>
</button>
</span>
</div>
</form>
</div>
</div>
<table class="table table-responsive table-hover" style="max-height:150px; height:100px;">
<thead>
<tr>
<th>#Html.DisplayNameFor(model => model.Name)</th>
<th>LAN ID</th>
<th>Department</th>
<th>Email</th>
</tr>
</thead>
<tbody>
#foreach(var x in Model)
{
<tr class="info">
<td>
#Html.DisplayFor(modelItem => x.Name)
</td>
<td>
#Html.DisplayFor(modelItem => x.Lan_Id)
</td>
<td>
#Html.DisplayFor(modelItem => x.CurrDept)
</td>
<td>
#Html.DisplayFor(modelItem => x.Email)
</td>
</tr>
}
</tbody>
</table>
<div class="panel-footer"></div>
make a table structure as follows. Should resolve your issue
<div class="table-responsive">
<table class="table table-striped table-bordered">
//rest of code
</table>
</div>

Exception handling using the modal

There was such task.
I have a controller method of removing
public ActionResult Delete(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
try {
TechnologicalCard technologicalCard = db.TechnologicalCards.Find(id);
db.TechnologicalCards.Remove(technologicalCard);
db.SaveChanges();
return RedirectToAction("Index");
}
catch (Exception ex)
{
ViewBag.Error = true;
TempData["message"] = "someMessage";
return RedirectToAction("Index");
}
}
How can I do that would be when an exception is thrown during the removal of the modal appeared with warning text ?
UPDATE
I added the index method
public ActionResult Index()
{
var id_Head = User.Identity.GetUserId();
TempData["message"] = "someMessage";
var technologicalCards = db.TechnologicalCards.Where(c => c.IdHeadDepartment == id_Head).ToList();
return View(technologicalCards);
}
My view has contains the following code
#model IEnumerable<AccountingPlusProject.Models.TechnologicalCard>
#{
ViewBag.Title = "Учёт+";
}
<style>
.md-form {
position: relative;
top: 40px;
width: 20%;
height: 20%;
text-align: center;
}
.img1 {
background-image: url("/Content/avatars/Head.jpg");
background-repeat: no-repeat;
width: 7%;
height: 65px;
border-style: none;
margin-left: 90%;
margin-top: -8%;
}
.img2 {
width: 7%;
height: 65px;
border-style: none;
margin-left: 80%;
}
h2 span {
color: white;
font: bold 24px/45px Helvetica, Sans-Serif;
letter-spacing: -1px;
background: rgb(0, 0, 0);
background: rgba(0, 0, 0, 0.7);
padding: 10px;
}
.demo-card-wide.mdl-card {
width: 512px;
}
.demo-card-wide > .mdl-card__title {
color: #fff;
height: 176px;
}
.demo-card-wide > .mdl-card__menu {
color: #fff;
}
.container {
margin: 30px auto;
width: 85%;
height: 100%;
}
.warningMessage {
font-weight: bold;
color: Red;
}
</style>
<script>
$(function () {
if ($('#myModal').length) {
$('#myModal').modal('show');
}
});
</script>
<nav class="navbar navbar-light teal lighten-4" style="height: 100px">
<div class="container">
<div class="collapse navbar-toggleable-xs" id="collapseEx2" style="margin-top:-2%">
<img src="~/Content/truelogo.png" style="margin-left:-10%" />
#Html.ActionLink("Добавить технологическую карту", "Create", null, new { #class = "btn btn-success" })
<img src="~/Content/avatars/Head.jpg" class="rounded-circle img-responsive img1">
#Html.ActionLink("Отмена", "Index", "HeadDepartment", null, new { #class = "btn btn-danger", #style = "margin-left:100%; margin-top:-11%" })
</div>
</div>
</nav>
<div class="page-content">
<div class="container">
#{int i = 1;}
<table>
#foreach (var item in Model)
{
if (i % 4 == 1)
{
<tr></tr>
}
<td>
<div class="card">
<img class="img-fluid" src="#item.Image" alt="Card image cap">
<div class="card-block">
<center>
<hr />
<h4 class="card-title">#item.NameProduct</h4>
<hr />
#item.Description
<hr />
#{ var materials = item.SelectedMaterials.ToList();}
#foreach (var material in materials)
{
#Html.DisplayFor(model => material.ReferenceMaterial.NameMaterial) <b> Штук: </b>
#Html.DisplayFor(model => material.CountMaterial)
<br />
}
<br />
<center>
#Html.ActionLink("Настроить материалы", "EditMaterial", new { id = item.IdTechnologicalCard }, new { #class = "btn btn-success" })
<br />
#Html.ActionLink("Настроить количество", "EditCountOfMaterial", new { id = item.IdTechnologicalCard }, new { #class = "btn btn-success" })
</center>
<hr />
#Html.ActionLink("Удалить", "Delete", new { id = item.IdTechnologicalCard }, new { #class = "btn btn-danger" })
</center>
</div>
</div>
</td>
i++;
}
</table>
</div>
#if (TempData["message"] != null)
{
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria- labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title" id="myModalLabel">Modal title</h4>
</div>
<div class="modal-body">
121212 <!--add your message here-->
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data- dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
}
</div>
But when I deleting redirects to Index view without modal
You can pass error messages using the model state dictionary as well. In that case, you should be returning the same view back to the user instead of a redirect, so that user can try the action again.
catch (Exception ex)
{
ModelState.AddModelError(string.Empty,"Error! Try again.");
return View();
}
Now make sure you have the Validation helper methods being used in the view to render the error messages from the model state dictionary.
#Html.ValidationSummary(false)
With this approach, only the id will be passed back to the view (basically read from the model state dictionary), not all other fields you had. If you want all fields, use the same view model (which your view is strongly typed to) as the method parameter.
Exception handling using the modal
As you made it clear that you want to show the error in a modal window here is what you can do.
You need to again assign this TempData data into another TempData with in your Index method. Since the TempData is only alive from one controller to another.
And add this code in your index view.
#if (TempData["message"] != null)
{
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title" id="myModalLabel">Modal title</h4>
</div>
<div class="modal-body">
#TempData["message"] <!--add your message here-->
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
}
Then add this script in your index.cshtml.
$(function(){
if($('#myModal').length){
$('#myModal').modal('show');
}
});

Resources