How to show and hide the data when the condition is true - javascript

In my angular application I have created the dashboard page. In that page I have created some conditions based on the condition it has to show on the view if the condition is false it will remove from the view page.
Dashboard.component.ts
var insidecirclespace1 = (lat,long) => {
for (var i=0; i< this.sensors.length;i++){
if (getDistanceFromLatLonInKm(this.sensors[i].latitude, this.sensors[i].longitude, lat,long) <= 5.0) {
circlemark[i].setStyle({ color: 'red', weight: 1, opacity: 7.0 });
"model": "1001",
"sensorname": "Sensor 1",
"rf": "1",
"Idref": "1"
});
}
}
outsidespace(latlngs[latlngidx1].lat,latlngs[latlngidx1].lon,latlngs02[latlngidx2].lat,latlngs02[latlngidx2].lon);
}
var insidecirclespace2 = (lat,long) => {
for (var i=0; i< this.sensors.length;i++){
if (getDistanceFromLatLonInKm(this.sensors[i].latitude, this.sensors[i].longitude, lat,long) <= 5.0) {
circlemark[i].setStyle({ color: 'red', weight: 1, opacity: 7.0 });
this.wifiDrones.push({
"model": "1002",
"sensorname": "Sensor 2",
"rf": "1",
"Idref": "1"
});
}
}
outsidespace(latlngs[latlngidx1].lat,latlngs[latlngidx1].lon,latlngs02[latlngidx2].lat,latlngs02[latlngidx2].lon);
}
var outsidespace = (lat1,long1,lat2,long2)=>{
for (var i=0; i< this.sensors.length;i++){
if (getDistanceFromLatLonInKm(this.sensors[i].latitude, this.sensors[i].longitude, lat1,long1) > 5.0 && getDistanceFromLatLonInKm(this.sensors[i].latitude, this.sensors[i].longitude, lat2,long2) > 5.0) {
circlemark[i].setStyle({ color: 'blue', weight: 1, opacity: 7.0 });
}
}
}
Based on the above condition the html page will show as
.component.html
<div class="col-sm-4">
<div class="card-body">
<h5 class="card-text " style="color: white;"> {{x.model}}
</h5>
<!--some code -->
</div>
</div>
Now my requirement is if the getdistanceInKm is less than 5 km It has to show the data on html page view if the distance is more than 5 km it has to remove (It will continuous for moving marker <5km or >5km)
It is coming for <5km for removing in >5km is not working can anyone please help me regarding this.

Using *ngIf will do the trick, you can use by providing your function inside the *ngIf or any property as follows:
using a propery:
in your ts file you could create a property for e.g. distance:
distance: number = 0;
and update your distance propery in your functions and using binding you could show and hide your HTML element as follows:
<div class="col-sm-4" *ngIf="distance < 5">
<div class="card-body">
<h5 class="card-text " style="color: white;"> {{x.model}}
</h5>
<!--some code -->
</div>
</div>
using a function, if the getdistanceInKm function will return a number this will do the job also:
<div class="col-sm-4" *ngIf="getdistanceInKm()< 5">
<div class="card-body">
<!--some code -->
</div>
</div>
Updated
Also you can use ViewChild as follows for changing the HTML element from ts file:
HTML file:
<div #distanceElement class="col-sm-4">
<div class="card-body">
<!--some code -->
</div>
</div>
ts file:
#ViewChild('distanceElement ') el:ElementRef;
and when changes occurs you can use:
this.el.nativeElement.style.display='none';

HTML
<div *ngIf="validation()">
<h5 class="card-text " style="color: white;"> {{x.model}}</h5>
</div>
.TS
validation() {
// logic if less than 5 km return
return true;
}
P.s This is just an overview, the syntax or the approach may not be perfect

Related

Javascript for loop only creates one child

I have an array of js objects, and for every object in array I am trying to create a div with a template, designated with <template></template>. I am trying to do this using a for loop. The for loop does exactly what I want, one time.
Here is my HTML template to be copied:
<template id="tracktemp">
<div class="trackerItem">
<div class="itemNameTextCont">
<p class="itemNameText">Combatant Name</p>
</div>
<div class="itemHpTextCont">
<p class="itemHpText">HP 100</p>
</div>
<div class="itemApTextCont">
<p class="itemApText">AP 30</p>
</div>
<div class="itemActionButtonsCont">
<div class="actionButtonCont"><button class="actionButton">Heal</button></div>
<div class="actionButtonCont"><button class="actionButton">Dam</button></div>
<div class="actionButtonCont"><button class="actionButton">Stat</button></div>
<div class="actionButtonCont"><button class="actionButton">Abil</button></div>
</div>
<div class="itemModifyButtonsCont">
<div class="modifyButtonCont"><button class="modifyButton">Edit</button></div>
<div class="modifyButtonCont"><button class="modifyButton">Remove</button></div>
</div>
</div>
</template>
The HTML Section it's being copied into (within trackerCont)
<section class="trackerModule">
<div class="trackerModuleCont">
<div class="trackerHeaderCont">
<h2 class="trackerHeader">Combatants</h2>
</div>
<div class="trackerTopButtonsCont">
<div class="topButtonCont"><button class="topButton">Add</button></div>
<div class="topButtonCont"><button class="topButton">Add From</button></div>
</div>
<div id="trackerCont" class="trackerCont">
</div>
<div class="trackerBottomButtonsCont">
<div class="bottomButtonCont"></div>
<div class="bottomButtonCont"></div>
</div>
</div>
</section>
And the JS doing the copying
var trackerArray = [
{Name: "Joe Brown", HP: 100, AP: 30},
{Name: "Steve Smith", HP: 100, AP: 30},
{Name: "Jane", HP: 100, AP: 30}
]
function buildTracker() {
var trackerLength = trackerArray.length;
var trackItemTemp = document.getElementById('tracktemp').content.cloneNode(true);
for (i = 0; i < trackerLength; i++) {
var combatant = trackerArray[i];
var itemParent = document.getElementById('trackerCont');
trackItemTemp.querySelector('.itemNameText').innerText = combatant.Name;
trackItemTemp.querySelector('.itemHpText').innerText = combatant.HP;
trackItemTemp.querySelector('.itemApText').innerText = combatant.AP;
document.createElement(trackItemTemp);
}
}
I understand to some extent that appendChild can only create one element. I should be using document.createElement instead, no? I do not understand how to go about rewriting the code to copy the HTML template using createElement... If someone could lend me a hand that would be great! Thanks!
From
document.createElement(trackItemTemp);
To
document.getElementById("trackerCont").appendChild(trackItemTemp);
(edit)
I missed whole function code and i also missed there was a variable itemParent so I edited the last line of the function. Make sure to use cloneNode in each loop.
function buildTracker() {
var trackerLength = trackerArray.length;
var trackItem;
for (i = 0; i < trackerLength; i++) {
var trackItemTemp = document.getElementById('tracktemp').content.cloneNode(true);
var combatant = trackerArray[i];
var itemParent = document.getElementById('trackerCont');
trackItemTemp.querySelector('.itemNameText').innerText = combatant.Name;
trackItemTemp.querySelector('.itemHpText').innerText = combatant.HP;
trackItemTemp.querySelector('.itemApText').innerText = combatant.AP;
itemParent.appendChild(trackItemTemp);
}
}

Automated id increment for bootstrap collapse component

Bootstrap's Collapse components require sections (or cards) with unique id to enable collapsing / decollapsing each section independently. I am trying to create multiple sections equal to the amount of data points using "v-for" from vue.js. However, I don't know how to automatically generate unique ids for the cards. this is what I tried:
<div id = "story-content" class="content">
<div v-for="(subchapter, chapter) in story" class="card">
<div class="card-header">
<a href = "'collapse' + generateNewId" class="card-link" data-toggle="collapse" >
[[chapter]]
</a>
</div>
<div id = "'collapse' + getCurrentId" class="collapse show" data-parent="#story-content" >
<div class="card-body">
[[subchapter]]
</div>
</div>
</div>
</div>
<script>
var story = {{story | safe}};
var app = new Vue({
delimiters: [ '[[', ']]'],
el: '#portofolio',
data: {
story: story,
uniqueId: 0,
},
methods: {
generateNewId: function() {
return uniqueId + 1;
},
getCurrentId: function() {
return uniqueId;
}
}
})
</script>
Example of the story data structure:
{
"Chapter1": {
"Subchapter1": {
"side_note": "January - June 2019",
"desc": "description here"
},
"Subchapter2": {
"side_note": "January - June 2019",
"desc": "description here"
}
},
"Chapter2": {
"Subchapter1": {
"side_note": "",
"desc": ""
}
}
}
P.S I am not using bootstrap-vue since I did not know its existence until in the middle of my learning. I'm a beginner in web development. Hopefully there is a way to solve this issue without the need of bootstrap-vue as I will need to modify other components as well.
Bootstrap 4 uses jQuery for the Collapse component. So, one way to solve it is to simply use the Chapter keys as the unique id's...
<div id="story-content" class="content">
<div v-for="(subchapter, chapter) in story" class="card">
<div class="card-header">
<a :href="'#collapse' + chapter" :data-target="'#collapse' + chapter" class="card-link"
data-toggle="collapse"> [[chapter]] </a>
</div>
<div :id="'collapse' + chapter"
class="collapse show" data-parent="#story-content">
<div class="card-body"> [[subchapter]] </div>
</div>
</div>
</div>
Demo: https://codeply.com/p/0DEYVY4HUA
However, using jQuery with Vue isn't desirable, so a better way would be to recreate the collapse behavior in Vue as explained here

Loading Laravel Chart consoletvs/charts:7.*

I am new to laravel charts.I thought following the documentation to make a sample chart will be a stepping stone. Having followed the documentation form adding the package into my project using composer require consoletvs/charts:7.* and publishing the configuration file by running php artisan vendor:publish --tag=charts and then creating a new chart with the command: php artisan make:chart SampleChart a SampleChart was made under App\Chart
In the SampleChart class i made the following chart configuration
public ?string $name = 'SampleChart';
public ?string $routeName = 'SampleChart';
public ?array $middlewares = ['auth'];
I then manually register using the App\Providers\AppServiceProvider with the code as stated from the documentation
public function boot(Charts $charts)
{
$charts->register([
\App\Charts\SampleChart::class
]);
}
On rendering the chart in my views; I put in the following code
<div id="chart" style="height: 300px;"> </div>
<!-- Charting library -->
<script src="{{ asset('js/Chart.min.js') }}"></script>//downloaded from https://unpkg.com/echarts/dist/echarts.min.js
<!-- Chartisan -->
<script src="{{ asset('js/chartisan_chartjs.js') }}">
</script> //downloaded from https://unpkg.com/#chartisan/echarts/dist/chartisan_echarts.js
<!-- Your application script -->
<script>
const chart = new Chartisan({
el: '#chart',
url: "#chart('SampleChart')",
loader: {
color: '#222',
size: [30, 30],
type: 'bar',
textColor: '#000',
text: 'Loading some chart data...',
},
});
</script>
the output is a flex item with a caption "Loading some chart data... " and nothing shows. Am Stucked
I used the tutorial form https://dev.to/arielmejiadev/use-laravel-charts-in-laravel-5bbm and https://izwebtechnologies.com/2019/06/03/how-to-create-charts-in-laravel/ but none was able to made me accomplish having a chart. though the two tutorial links are for chart6.* i later read the two have different approaches to chart design.
I am Usning Laravel7 and charts:7.*
i am the author.
Some of the issues may be releated to laravel charts, and others to chartisan. I am doing my best to keep everybody happy here but seems people are not happy with the docs.
I am creating an example page with all sorts of examples on chartisan's page.
Remember laravel charts now only acts as a wrapper around chartisan's php package.
Its such a big project for a single person and i like to see constructive feedback.
What exacly isn't clear from the chartisan docs?
try to run without public ?array $middlewares = ['auth']; set.
just public ?array $middlewares = [];
^^^^^^^^^^ this is how I used with Laravel package ^^^^^^^^^^
vvvvvvvvvvvvvvvvvvvv This is how I use now vvvvvvvvvvvvvvvvvvvv
After some time using the ConsoleTV/Charts I decided not to use it like Laravel package.
I get rid of any use of it and use the javascript version only.
To get the data I did this:
Create a controller named whatever you want and put a function like this:
public function chartSample1()
{
$data = array(
"chart" => array(
"labels" => ["First", "Second", "Third"]
),
"datasets" => array(
array("name" => "Sample 1", "values" => array(10, 3, 7)),
array("name" => "Sample 2", "values" => array(1, 6, 2)),
)
);
return $data;
}
On the "routes/web.php" added:
Route::get('/chartSample1', 'MyChartController#chartSample1')->name('chartSample1');
And on the page:
#extends('layouts.app')
#section('content')
<div class="row justify-content-center">
<div class="col-sm-12 align-self-center">
<div class="row">
<div class="col-lg-3">
<div class="card shadow p-3 mb-5 bg-white rounded">
<div class="card-body">
<h5 class="card-title">Special title treatment</h5>
<div id="chart" style="height: 300px;"></div>
Go somewhere
</div>
</div>
</div>
<div class="col-lg-3">
<div class="card shadow p-3 mb-5 bg-white rounded">
<div class="card-body">
<h5 class="card-title">Special title treatment</h5>
<div id="chart2" style="height: 300px;"></div>
Go somewhere
</div>
</div>
</div>
<div class="col-lg-3">
<div class="card shadow p-3 mb-5 bg-white rounded">
<div class="card-body">
<h5 class="card-title">Special title treatment</h5>
<div id="chart3" style="height: 300px;"></div>
Go somewhere
</div>
</div>
</div>
<div class="col-lg-3">
<div class="card shadow p-3 mb-5 bg-white rounded">
<div class="card-body">
<h5 class="card-title">Special title treatment</h5>
<p class="card-text">With supporting text below as a natural lead-in to additional content.</p>
Go somewhere
</div>
</div>
</div>
</div>
</div>
</div>
{{-- This script has more features --}}
<script src="https://unpkg.com/chart.js/dist/Chart.min.js"></script>
<script src="https://unpkg.com/#chartisan/chartjs/dist/chartisan_chartjs.js"></script>
{{--
<script src="https://unpkg.com/echarts/dist/echarts.min.js"></script>
<script src="https://unpkg.com/#chartisan/echarts/dist/chartisan_echarts.js"></script>
--}}
</script>
<script>
const chart = new Chartisan({
el: '#chart',
url: "{{ route('chartSample1') }}",
hooks: new ChartisanHooks()
.colors(['#ECC94B', '#4299E1'])
.legend()
loader: {
color: '#ff00ff',
size: [30, 30],
type: 'bar',
textColor: '#11ff00',
text: 'Loading some chart data...',
}
});
const chart2 = new Chartisan({
el: '#chart2',
data: {
chart: { "labels": ["First", "Second", "Third"] },
datasets: [
{ "name": "Sample 1", "values": [10, 3, 7] },
{ "name": "Sample 2", "values": [5, 6, 2] }
],
},
hooks: new ChartisanHooks()
.colors(['#ECC94B', '#4299E1', '#AAEE11'])
.legend({ position: 'left' })
.beginAtZero()
.datasets([{ type: 'line', fill: false }, 'bar']),
});
const chart3 = new Chartisan({
el: '#chart3',
data: {
chart: { "labels": ["First", "Second", "Third"] },
datasets: [
{ "name": "Sample 1", "values": [10, 3, 7] },
],
},
hooks: new ChartisanHooks()
.colors(['#ECC94B', '#4299E1', '#AAEE11'])
.datasets([{ type: 'pie', fill: true }, 'pie']),
});
</script>
I had a similar problem and I've been able to solve it. The configuration in your chart class is not compulsory. You can choose to ignore them.
Your render url is also wrong. It is supposed to be in snake case:
//SampleChart will be
#chart('sample_chart')
//PostData will be
#chart('post_data')
If you specified the route in your Chart class, you will have to use that: #chart('your_route'). If you don't know your route, use the php artisan route:list -c command to check.
If you want to specify the type of chart, you have to use hooks.
I ran into a bit of an issue myself. Everything Works for line chart and bar chart, but i can't present a pie chart. The Doughnut is also not working.

Checking a substring from a programmatically added element in VueJs

I have a form that adds a new line on a button click. The new line must check for logic independently. In this case, it's chacking the first 2 digits of a barcode and associating it to a data set to see if it matches and return the appropriate value or "nothing found". I can't seem to get this right. First, it's not really evaluating at all. It only gives me "No Agency found" and second, it's doing it for all fields (because they all have the same v-model on a new line add). How can I achieve this so that it evaluates correctly and independently from each other?
Here's the relevant code in my template and script
<div id="q-app" class="q-pa-lg">
<div class="col-6">
<div v-for="(barcodefield, index) in barcodefields" :key="index">
<div class="flex q-pt-lg">
<div class="row flex-center">
<div class="col-3">
<div class="column">
<div class="row q-pr-lg items-center">
<label class="text-weight-medium">Starting Roll #:</label>
<q-input outlined square dense maxlength="24"
v-model.trim="barcodefield.start" ref="bcentry"></q-input>
</div>
</div>
</div>
<div class="col-3">
<div class="column">
<div class="row q-pr-lg items-center">
<label class="text-weight-medium">Ending Roll #:</label>
<q-input outlined square dense maxlength="24"
v-model.trim="barcodefield.end" #blur="showAgencyName" ref="bcentry"></q-input>
</div>
</div>
</div>
<div class="col-5">
<div class="column">
<label class="text-weight-medium">
Agency:
</label>
<div v-if="agencyName" style="min-height: 40px">
{{ agencyName }}
</div>
<div v-else style="min-height: 40px"></div>
</div>
</div>
<div class="col-1">
<div class="block float-right">
<q-btn v-if="index + 1 === barcodefields.length" #click="addLine" icon="add" color="primary" round />
<q-btn v-else style="min-width: 42px"/>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
export default {
data() {
return {
barcodefields: [],
barcodeprefixes: {
"10": "Boston",
"11": "New York",
"13": "Houston",
"14": "Connecticut",
"16": "SIA",
"17": "Colorado",
"18": "Chicago",
"19": "Washington",
},
barcodefield: {
star: "",
end: ""
},
agencyName: "",
};
},
methods: {
addLine() {
this.barcodefields.push({
start: null,
end: null
});
},
showAgencyName() {
var str = this.barcodefield.end;
var res = str.substring(0, 2);
if (this.barcodeprefixes[res] == undefined) {
this.agencyName = "Agency not found";
} else {
this.agencyName = this.barcodeprefixes[res];
}
},
},
mounted() {
this.addLine();
}
}
Here is a codepen for you.
There are several things going on here:
First, as Simon points out, don't name loop variables the same thing as a top-level data element. Instead of <div v-for="(barcodefield, index) in barcodefields" :key="index">, do <div v-for="(item, index) in barcodefields" :key="index">. Then update all the barcodefield.start and barcodfield.end references to item.start and item.end.
Then, you need to get each item to have its own agencyName, instead of all of them referring to the same data.
Update showAgencyName to this:
showAgencyName(item) {
var str = item.end;
var res = str.substring(0, 2);
if (this.barcodeprefixes[res] == undefined) {
item.agencyName = "Agency not found";
} else {
item.agencyName = this.barcodeprefixes[res];
}
},
Then you can call it like this: #blur="showAgencyName(item)"
And use it in the html like so:
<div v-if="item.agencyName" style="min-height: 40px">
{{ item.agencyName }}
</div>
(And you can get rid of the top-level barcodefield in the data object, because it's not used anymore.)
Fiddle here:
https://jsfiddle.net/ebbishop/7r1pqx9f/
First you should change name of the for loop variable named "barcodefield", beacause you already have one in your data structure
Second, i would personnaly use a function {{ getAgencyName(b) }} instead of {{ agencyName }} otherwise you will have same agency name for all lines
There are a couple of problem with this.
First, you have a typo in the barcodefield data object. You have "star" instead of "start".
Secondly in the showAgency method you are referencing the this.barcodefield properties but that doesn't exist.
What you can do is pass the index of the barcodefield to the showAgencyName method, and use that inside the method to get the desired barcodefield from the barcodefields array.
In your html:
<q-input outlined square dense maxlength="24"
v-model.trim="barcodefield.end" #blur="showAgencyName(index)" ref="bcentry"></q-input>
and the showAgencyName method:
showAgencyName(index) {
const barcodefield = this.barcodefields[index]
var str = barcodefield.end;
var res = str.substring(0, 2);
if (this.barcodeprefixes[res] == undefined) {
this.agencyName = "Agency not found";
} else {
this.agencyName = this.barcodeprefixes[res];
}
}
UPDATE:
There is another problem that I didn't notice at first. The agencyName is overwritten every time you add a new barcodefield since it is kind of a global value.
I update the Codepen with the simplest solution I could think of. Return the name of the agency from the showAgencyName and use that to print it on the interface. There are many possible other solutions to this (for example add the name the the barcodefields object in the array).
Here is a working Codepen

Rotate Styles using Angular ng-if

Still learning angular, but having issues rotating styles. Ultimately, I want the first record to be blue, the second to be white, the third blue, the fourth white, etc...
Right now my order is (incorrect):
Record 1 Blue
Record 3 blue
Record 2 white
Record 4 white
Any ideas what could be the issues?
HTML
<div id="dashboard" style="width: 1100px;" ng-controller="controller4">
<div class="blue" ng-repeat="metrics in dashboard" ng-if="($index % 2 == 0)">
<div align="center">
<h3>{[{metrics.value}]}</h3>
<span class=dashboardtext>{[{metrics.name}]}</span>
</div>
</div>
<div class="white" ng-repeat="metrics in dashboard" ng-if="($index % 2 != 0)">
<div align="center">
<h4>{[{metrics.value}]}</h4>
<span class=dashboardtext>{[{metrics.name}]}</span>
</div>
</div>
</div>
JS
var dashboard = [
{
value: 15,
name: "Total Completed"
},
{
value: 1200,
name: "Additional Widgets Sold"
},
{
value: 16,
name: "Projects"
},
{
value: 5,
name: "Average Days"
}
];
myApp.controller('controller4', function($scope) {
$scope.dashboard = dashboard;
});
ng-class-even & ng-class-odd directive perfectly suits your need.
ng-class-even -> Add a class value to DOM classList object when $index
is even
ng-class-odd -> Add a class value to DOM classList object when
$index is odd
Markup
<div ng-class="'blue'" ng-class-odd="'white'" ng-repeat="metrics in dashboard">
<div align="center">
<h3>{[{metrics.value}]}</h3>
<span class=dashboardtext>{[{metrics.name}]}</span>
</div>
</div>
For simple even/odd, you can use the ng-class-even and ng-class-odd attributes. If you have a more complex situation with more values, use the below solution.
Create a filter and use it in the class attribute.
app.filter("classFilter", function () {
return function (input) {
var $class = "";
switch(input % 2){
case 0:
$class = "blue";
break;
case 1:
$class = "white";
break;
}
return $class;
}
});
Then in your HTML, you would have
<div class="$index | classFilter" ng-repeat="metrics in dashboard">
<div align="center">
<h3>{[{metrics.value}]}</h3>
<span class=dashboardtext>{[{metrics.name}]}</span>
</div>
</div>

Categories