Apply different styles to bootstrap card - javascript

I'm working with Angular 9 with a Bootstrap 4 card applying NGFOR to paint as many elements as come from the database.
I have the following array with different styles for that card and I would like them to be applied to each one in a random way.
public color_border = ["border-left-warning", "border-left-info", "border-left-primary"]
The card code is as follows: the div card border-left-info has to be changed. I have tried a new NGFOR but it duplicates everything.
<!-- Pending Requests Card Example -->
<div class="col-xl-3 col-md-6 mb-4" *ngFor="let data of miDataInterior.DatagreenhouseRecuperado; let i = index">
<div class="card border-left-info shadow h-100 py-2">
<div class="card-body">
<div class="row no-gutters align-items-center">
<div class="col mr-2">
<div class="text-xs font-weight-bold text-warning text-uppercase mb-1">{{data.medidas[0].sensor_type[0].name_comun}}</div>
<font SIZE=3> {{data.medidas[0].marca}} </font>
<font SIZE=3>({{data.medidas[0].recvTime | date:'dd-MM-yy h:mm:ss a'}})</font>
<div class="h5 mb-0 font-weight-bold text-gray-800">{{data.medidas[0].attrValue | number:'1.0-1'}} {{data.medidas[0].sensor_type[0].medida}}</div>
</div>
<div class="col-auto">
<i class="fas fa-chart-bar fa-2x text-gray-300"></i>
</div>
</div>
</div>
</div>
</div>
How could I apply what is contained in the color_border variable in that div?
Error:
<!-- Pending Requests Card Example -->
<div class="col-xl-3 col-md-6 mb-4" *ngFor="let data of miDataInterior.DatagreenhouseRecuperado; let i = index">
<div *ngFor="let color_border of color_border" class="card {{color_border}} shadow h-100 py-2">
<div class="card-body">
<div class="row no-gutters align-items-center">
<div class="col mr-2">
<div class="text-xs font-weight-bold text-warning text-uppercase mb-1">{{data.medidas[0].sensor_type[0].name_comun}}</div>
<font SIZE=3> {{data.medidas[0].marca}} </font>
<font SIZE=3>({{data.medidas[0].recvTime | date:'dd-MM-yy h:mm:ss a'}})</font>
<div class="h5 mb-0 font-weight-bold text-gray-800">{{data.medidas[0].attrValue | number:'1.0-1'}} {{data.medidas[0].sensor_type[0].medida}}</div>
</div>
<div class="col-auto">
<i class="fas fa-chart-bar fa-2x text-gray-300"></i>
</div>
</div>
</div>
</div>
</div>
Thanks for your help.
EDIT
I am testing directly on NGCLASS, the problem is that it only shows the style of the last element in the array. How can I fix this?
<div class="card shadow h-100 py-2" [ngClass]="['border-left-primary', 'border-left-info', 'border-left-warning']">

Alternate border
[ngClass]="color_border[i%3]"
A random you need make a function (you can not use Math inside the .html)
[ngClass]="getRandomColor()"
getRandomColor()
{
return this.color_border[Math.floor(Math.random()*this.color_border.length]
}
If you miDataInterior.DatagreenhouseRecuperado has a property "color" from 0 to 2 you can use
[ngClass]="color_border[data.color]"
NOTE there're severals ways to use [ngClass], see the docs

Try this..
<div *ngFor="let color_border of color_border" class="card shadow h-100 py-2 " [ngClass]="{{color_border}}">

Related

Create a dynamic div with JavaScript

I have created a page of feeds in which a new post should be created and shown in the user's feed. Lets say the div will look like this
In the textarea the data is entered and then on click of the post button the lower div is created
I have done this in javascript but the name, image, all data is simply entered by me but it should come from the controller I cant use the simple approach like I have done in HTML page how can it be done in javascript?
<body>
<textarea class="form-control border-0 p-0 fs-xl" rows="4" id="input" placeholder="What's on your mind Codex?..."></textarea>
<button class="btn btn-info shadow-0 ml-auto " id="submit" onclick="addCode()">Post</button>
<div id="add_after_me">
<div class="test " >
</div>
</div>
<script>
$('#submit').click(function () {
var text = $('#input').val();
$('#newDivs').append('<div class="test">' + text + '</div>');
});
function addCode() {
document.getElementById("add_after_me").insertAdjacentHTML("afterend",
'<div class="card mb-g"> < div class= "card-body pb-0 px-4" ><div class="d-flex flex-row pb-3 pt-2 border-top-0 border-left-0 border-right-0"><div class="d-inline-block align-middle status status-success mr-3"> <span class="profile-image rounded-circle d-block" style="background-image:url(); background-size: cover;"></span> </div> <h5 class="mb-0 flex-1 text-dark fw-500"> Dr. John Cook PhD <small class="m-0 l-h-n">Human Resources & Psychiatry Division</small></h5><span class="text-muted fs-xs opacity-70"> 3 hours </span> </div> <div class="pb-3 pt-2 border-top-0 border-left-0 border-right-0 text-muted " id="newDivs"> </div> </div ></div > ');
}
</script>
</body>
here is my code
I'm assuming that you have a Controller that can receive POST data, will handle it, then will respond an JSON with all the processed data that you want your Javascript to display.
We will use simple Ajax with jQuery here. We will start by sending the form via post to your controller when you submit the form, then we will assume that your controller respond a json with the same data once it's done. Then javascript will read the Json responded, and update the DOM.
Here is your code :
<body>
<textarea class="form-control border-0 p-0 fs-xl" rows="4" id="input" placeholder="What's on your mind Codex?..."></textarea>
<button class="btn btn-info shadow-0 ml-auto " id="submit" onclick="addCode()">Post</button>
<div id="add_after_me"></div>
<script>
$('#submit').click(function () {
$.post('/your-controller', {
text: $('#input').val()
}, function(data) {
const json = jQuery.parseJSON(data)
addCode(json)
})
});
function addCode(data) {
const addAfterMe = $("#add_after_me")
const template = `
<div class="card mb-g">
<div class= "card-body pb-0 px-4">
<div class="d-flex flex-row pb-3 pt-2 border-top-0 border-left-0 border-right-0">
<div class="d-inline-block align-middle status status-success mr-3">
<span class="profile-image rounded-circle d-block" style="background-image:url('${data.image}'); background-size: cover;"></span>
</div>
<h5 class="mb-0 flex-1 text-dark fw-500">
${data.fullname}
<small class="m-0 l-h-n">${data.department}</small>
</h5>
<span class="text-muted fs-xs opacity-70">
${data.time}
</span>
</div>
<div class="pb-3 pt-2 border-top-0 border-left-0 border-right-0 text-muted" id="newDivs">${data.text}</div>
</div>
</div>`
addAfterMe.append(template)
}
</script>
</body>
To create your "card", I use "Template Literals" javascript standard. But feel free to use whatever strategy you want.
So, each time that you will submit your form, the text will be sent to the Controller. Assuming that your controller will response this JSON :
{
'text': "Lorem Ipsum",
'image': "https://url-to-your-profile-image.com/image.png",
'fullname': 'Dr. John Cook PhD',
'department': 'Human Resources & Psychiatry Division',
'time': '3 hours'
}
And voila :)
I hope it helps !

Showing a button that pushes all other elements to the side (CSS Transition)

Basically, I'm having cards that have a height set by the flex behaviour. I'd like to add a button from the side that is only shown when the card is hovered so the button would come out from the right side of the container with a transition and start expanding and pushing all other content to the left until it finishes expanding. Therefore, I've looked for hours and I tried many things out and I couldn't find a solution. Could someone please help me out on this? here is my code, I'm using Bootstrap 5. Here is the UI I created
Here is my code . I'm using VueJS and my data is coming from an API.
<template>
<div class="d-flex col-12 flex-column bd-highlight mb-3">
<div class=" d-flex border border-dark col-12 flex-column" v-for="(question,index) in questions" :key="question + index">
<div class="d-flex col-12 justify-content-between">
<div>
<span class="text-wrap text-break">{{question.description}}</span>
</div>
<div class="d-flex">
<span :class="question.complexity.toLowerCase() === 'easy' ? 'badge bg-success align-self-start' : question.complexity.toLowerCase() === 'medium' ? 'badge bg-warning align-self-start' : 'badge bg-danger align-self-start' ">{{question.complexity}}</span>
</div>
</div>
<div class="d-flex flex-wrap">
<div class="p-2" v-for="(tag,index1) in question.tags" :key ="tag + index1">
<span class="badge bg-dark text-white"><i :class="'devicon-'+tag.nom.toLowerCase()+'-plain'"></i> {{tag.nom}}</span>
</div>
<div class="align-items-center d-flex w-100 justify-content-end">
<span>
<i class="fas fa-stopwatch"></i> {{question.duree}} secs </span></div>
</div>
</div>
</div>
</template>
Here is my UI
Expected Result ( Buttons should be with the same size )

JavaScript trying to append to HTML not working

I am trying to create a simple eCommerce website with HTML, CSS, and JavaScript. When a user adds an item to their cart I add that item to local storage and I want when the user goes to their cart, all the items in local storage are read and then displayed to the cart. Whenever I try to append I get this. Instead of displaying the HTML it displays a string of all the HTML?
function getCartItems() {
var items = JSON.parse(localStorage.getItem("cartItems"));
console.log({ items });
for (let i = 0; i < items.length; i++) {
console.log(items[i]);
var cartRow = document.createElement("div");
// cartRow.classList.add("cart-row");
var cartItems = document.getElementsByClassName("cart-items")[0];
var cartRowContents = ` <li class="list-group-item d-flex flex-column">
<div class="row">
<div class="col col-lg-4">
<img
src="${items[i].image}"
alt="${items[i].name}"
class="d-block mx-auto"
/>
</div>
<div class="col col-lg-2 text-center">
<h5 class="mt-4 flex-wrap">${items[i].name}</h5>
<p>Size: 10.5</p>
<h2><span class="badge badge-danger">$189.99</span></h2>
</div>
<div class="col mt-4 text-center">
<p class="font-weight-bold">Quantity</p>
<input type="number" value="1" class="pl-2 w-50 rounded cart-quantity" />
<button
class="btn border border-none mx-5 mt-3 mt-lg-0 remove-item"
>
<i class="far fa-trash-alt"> </i>
</button>
</div>
</div>
</li>`;
cartRow.innerText = cartRowContents;
cartItems.append(cartRow);
}
}
Here is the code for my HTML
<!-- Cart -->
<div class="card m-5 border border-none mw-50">
<div class="card-header text-center text-white bg-primary">
Your Order
</div>
<ul class="list-group list-group-flush cart-items">
<li class="list-group-item d-flex flex-column">
<div class="row">
<div class="col col-lg-4">
<img
src="./images/products/air-max-270.jpg"
alt="Air Max 270"
class="d-block mx-auto"
/>
</div>
<div class="col col-lg-2 text-center">
<h5 class="mt-4 flex-wrap">Nike Air Max 270</h5>
<p>Size: 10.5</p>
<h2><span class="badge badge-danger">$189.99</span></h2>
</div>
<div class="col mt-4 text-center">
<p class="font-weight-bold">Quantity</p>
<input type="number" value="1" class="pl-2 w-50 rounded cart-quantity" />
<button
class="btn border border-none mx-5 mt-3 mt-lg-0 remove-item"
>
<i class="far fa-trash-alt"> </i>
</button>
</div>
</div>
</li>
</ul>
Call appendChild with innerHTML:
var cartItems = document.getElementsByClassName("cart-items")[0];
var cartRow = document.createElement("div");
cartRow.innerHTML = cartRowContents;
cartItems.append(cartRow);
Note: innerHTML is only destructive when used in combination with the += operator, as it causes a DOM refresh. It's all right to use it with createElement, as you're only changing the child's innerHTML, not the entire DOM. Reference
It seems you have confused Element.innerHTML with HTMLElement.innerText, as the latter sets your String to be the Node's actual text, not its HTML.
However, since it is discouraged to use Element.innerHTML for manipulating a Node's HTML, you should instead use Element.insertAdjacentHTML() instead.
This is because you are using innerText. You can use innerHtml instead but it's not recommended.
The way you are doing this, the only way you can pull it off is by using innerHTML like your last answer. However, if you want to do it the 'recommended' way, I would recommend using something called HTML DOM. You can recode all that you did simply by using the concept of creating elements and then appending them to each other and, finally, your cart. Here is the simple concept:
https://www.w3schools.com/js/js_htmldom.asp

Neet help in creating the parent/child structure in Jquery

I have the following HTML :
I'm trying to send the <p>{{ $comment->comment }}</p> to a Jquery function, upon clicking on the Edit button. I need help in completing the below structure :
Comment = event.target.parentNode.childNodes[1];
<div class=" p-3 border-top border-bottom bg-light">
<div class="d-flex align-items-center osahan-post-header">
<div class="dropdown-list-image mr-3 mb-auto"><img class="rounded-circle" src="img/p8.png" alt=""></div>
<div class="mr-1">
<div class="text-truncate h6 mb-3">{{ $comment->user->first_name }} {{ $comment->user->last_name }}</div>
<p>{{ $comment->comment }}</p>
</div>
<span class="ml-auto mb-auto">
<div class="text-right text-muted pt-1 small">{{ $comment->created_at}}</div>
</span>
</div>
<div class="post" align="right" data-postid="{{ $comment->id }}">
Edit
</div>
</div>
</div>
If you would fix your invalid HTML (as already mentioned in a comment, a <div> can't be inside a <span>), you could get the comment as follows:
document.getElementById("eid").onclick = function(e) {
let comment = e.target.closest(".p-3").getElementsByTagName("p")[0].innerHTML;
console.log(comment);
};
or, if you would use jQuery:
$("#eid").on("click", function(){
let comment = $(this).closest(".p-3").find("p").text();
console.log(comment);
});

Creating a custom filter for ng-repeat

I'm trying to create a filter inside an ng-repeat. What i'm trying to achieve is a list -> more information on button click combination. I'm using the prestashop webservice for retrieving data. All the data is pulled from a json object.
So i did try some other solutions found on stack but sadly those didn't work for me. See the following example:
So my html exists of 2 blocks. One is a list of all orders, shortly summarized by id, date and the total payed amount. The other block would be the more information section. This section would show wich products were ordered, at what date, etc.
So i've created the list and made the div (each list item) a clickable element by adding ng-click. (yes i did also try a <button ng-click="function()"> but since it didn't made any difference between using the div or the button i've chosen for the div (layout).
So the onclick event grabs the order.id and adds it to a filter. This filter is then applied on the second "more information" block. This block should then filter this id and only grab that information. But thats where i've stranded since this part is still not working. So what i've tried so far is shown below:
My HTML
var myApp = angular.module('myApp',['ngRoute','cgNotify','pascalprecht.translate','ngCookies','ngSanitize']);
// Orders
myApp.controller('OrderController', function($scope, $http){
$http.get('config/get/getOrders.php').then(function(response){
$scope.orders = response.data.orders.order
});
$scope.currentOrder = {
"id": 3
};
console.log($scope.currentOrder);
$scope.showOrder = function(order) {
var order_id = order.id;
$scope.currentOrder = {
"id": parseInt(order_id)
};
console.log($scope.currentOrder);
return $scope.currentOrder;
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<!-- The list -->
<div class="col-lg-12" ng-controller="OrderController">
<div class="container">
<form class="defaultinput col-xl-5 col-lg-6 col-md-8 d-flex justify-content-start">
<svg class="align-self-center d-flex" height="20px" version="1.1" viewbox="7 5 20 20" width="20px" xmlns="http://www.w3.org/2000/svg">
<defs></defs>
<path d="M27,23.5376923 L20.7969231,17.3046154 C21.7538462,16.0192308 22.3276923,14.4292308 22.3276923,12.7007692 C22.3276923,8.44769231 18.8969231,5 14.6638462,5 C10.4307692,5 7,8.44769231 7,12.7007692 C7,16.9538462 10.4307692,20.4015385 14.6638462,20.4015385 C16.4084615,20.4015385 18.0123077,19.8092308 19.3,18.8223077 L25.4476923,25 L27,23.5376923 L27,23.5376923 Z M8.35846154,12.7007692 C8.35846154,9.20692308 11.1869231,6.36461538 14.6638462,6.36461538 C18.1407692,6.36461538 20.9692308,9.20692308 20.9692308,12.7007692 C20.9692308,16.1946154 18.1407692,19.0369231 14.6638462,19.0369231 C11.1869231,19.0369231 8.35846154,16.1946154 8.35846154,12.7007692 L8.35846154,12.7007692 Z" fill="#8E8E93" fill-rule="evenodd" id="Search-Icon" stroke="none"></path></svg>
<input class="form-control" placeholder="{{ 'Zoeken' | translate }}" type="text">
</form>
<div class="row listrow" ng-repeat="order in orders">
<div ng-click="showOrder(order)" class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
<div class="col-lg-3">
<p type="number" ng-bind="order.id" ng-value="order.id"></p>
</div>
<div class="col-lg-4">
<p ng-bind="order.invoice_date"></p>
</div>
<div class="col-lg-5">
<p ng-bind="order.total_paid_real"></p>
</div>
</div>
</div>
</div>
</div>
<!-- The more information block -->
<div class="col-lg-11" ng-controller="OrderController">
<div>
<div ng-repeat="order in orders | filter: currentOrder" class="text-center margin-t-10">
<div class="row listrow"></div>
<h1>{{ 'Totaal' | translate }}</h1><h1 ng-bind="order.id"></h1>
<h3>#010 - {{ 'Contant' | translate }} {{ 'Betaald' | translate }}</h3>
</div>
<div class="row listrow margin-t-20 no-border">
<div class="col-6">
Blauw shirt - Maat: L
</div>
<div class="col-1">
2x
</div>
<div class="col-5 text-right">
€ 200,00
</div>
</div>
<div class="row listrow no-border">
<div class="col-6">
Blauw shirt - Maat: L
</div>
<div class="col-1">
2x
</div>
<div class="col-5 text-right">
€ 200,00
</div>
</div>
<div class="row margin-t-30 justify-content-end">
<div class="col-6">
<div class="row">
<div class="col-6">
{{ 'Subtotaal' | translate }}
</div>
<div class="col-6 text-right">
€ 400,00
</div>
</div>
<div class="row listrow">
<div class="col-6">
21% {{ 'BTW' | translate }}
</div>
<div class="col-6 text-right">
€ 84,00
</div>
</div>
<div class="row">
<div class="col-5 padding-r-5">
{{ 'Totaal' | translate }}
</div>
<div class="col-3 align-self-center no-padding">
<h6>(2 items)</h6>
</div>
<div class="col-4 padding-l-0 text-right">
€ 484,00
</div>
</div>
</div>
</div>
</div>
<div class="row margin-t-100 d-flex justify-content-around">
<button ng-click="" type="button" class="smallbutton defaultbutton">{{ 'Print bon' | translate }}</button>
<a href="#/refund">
<button type="button" class="smallbutton defaultbutton">{{ 'Retour' | translate }}</button>
</a>
</div>
</div>
The JSON example
{"orders":{"order":[{"id":"1","id_address_delivery":"4","id_address_invoice":"4","id_cart":"1","id_currency":"1","id_lang":"1","id_customer":"1","id_carrier":"2","current_state":"5","module":"ps_checkpayment","invoice_number":"4","invoice_date":"2017-03-16 15:18:27","delivery_number":"4","delivery_date":"2017-03-16 15:18:27","valid":"1","date_add":"2017-03-16 14:36:24","date_upd":"2017-03-16 15:18:27","shipping_number":{"#attributes":{"notFilterable":"true"}},"id_shop_group":"1","id_shop":"1","secure_key":"b44a6d9efd7a0076a0fbce6b15eaf3b1","payment":"Payment by check","recyclable":"0","gift":"0","gift_message":{},"mobile_theme":"0","total_discounts":"0.000000","total_discounts_tax_incl":"0.000000","total_discounts_tax_excl":"0.000000","total_paid":"55.000000","total_paid_tax_incl":"55.000000","total_paid_tax_excl":"55.000000","total_paid_real":"55.000000","total_products":"53.000000","total_products_wt":"53.000000","total_shipping":"2.000000","total_shipping_tax_incl":"2.000000","total_shipping_tax_excl":"2.000000","carrier_tax_rate":"0.000","total_wrapping":"0.000000","total_wrapping_tax_incl":"0.000000","total_wrapping_tax_excl":"0.000000","round_mode":"0","round_type":"0","conversion_rate":"1.000000","reference":"XKBKNABJK","associations":{"order_rows":{"#attributes":{"nodeType":"order_row","virtualEntity":"true"},"order_row":[{"id":"1","product_id":"2","product_attribute_id":"10","product_quantity":"1","product_name":"Blouse - Color : White, Size : M","product_reference":"demo_2","product_ean13":{},"product_isbn":{},"product_upc":{},"product_price":"26.999852","unit_price_tax_incl":"27.000000","unit_price_tax_excl":"27.000000"},{"id":"2","product_id":"3","product_attribute_id":"13","product_quantity":"1","product_name":"Printed Dress - Color : Orange, Size : S","product_reference":"demo_3","product_ean13":{},"product_isbn":{},"product_upc":{},"product_price":"25.999852","unit_price_tax_incl":"26.000000","unit_price_tax_excl":"26.000000"}]}}},{"id":"2","id_address_delivery":"4","id_address_invoice":"4","id_cart":"2","id_currency":"1","id_lang":"1","id_customer":"1","id_carrier":"2","current_state":"5","module":"ps_checkpayment","invoice_number":"3","invoice_date":"2017-03-16 15:18:27","delivery_number":"3","delivery_date":"2017-03-16 15:18:27","valid":"1","date_add":"2017-03-16 14:36:24","date_upd":"2017-03-16 15:18:27","shipping_number":{"#attributes":{"notFilterable":"true"}},"id_shop_group":"1","id_shop":"1","secure_key":"b44a6d9efd7a0076a0fbce6b15eaf3b1","payment":"Payment by check","recyclable":"0","gift":"0","gift_message":{},"mobile_theme":"0","total_discounts":"0.000000","total_discounts_tax_incl":"0.000000","total_discounts_tax_excl":"0.000000","total_paid":"75.900000","total_paid_tax_incl":"75.900000","total_paid_tax_excl":"75.900000","total_paid_real":"75.900000","total_products":"73.900000","total_products_wt":"73.900000","total_shipping":"2.000000","total_shipping_tax_incl":"2.000000","total_shipping_tax_excl":"2.000000","carrier_tax_rate":"0.000","total_wrapping":"0.000000","total_wrapping_tax_incl":"0.000000","total_wrapping_tax_excl":"0.000000","round_mode":"0","round_type":"0","conversion_rate":"1.000000","reference":"OHSATSERP","associations":{"order_rows":{"#attributes":{"nodeType":"order_row","virtualEntity":"true"},"order_row":[{"id":"3","product_id":"2","product_attribute_id":"10","product_quantity":"1","product_name":"Blouse - Color : White, Size : M","product_reference":"demo_2","product_ean13":{},"product_isbn":{},"product_upc":{},"product_price":"26.999852","unit_price_tax_incl":"27.000000","unit_price_tax_excl":"27.000000"}
To make it easier i've also created a JSfiddle
So my question is, since the first set of the filter is working (3). Why isn't my on click function working? with the console.log() i checked if the id is selected and it is. So why isn't the filter updated?
If you have any questions please ask them as comments.
As always, Thanks in advance!

Categories