how to pass values with their labels on click event in angular4 - html

I want to hide the li when clicking the plus button. here my data are passing but li is not clearing .(my output is like when clicking the plus button the datas are move but still the li is there.i want to remove the li instance)
my html code is
<div class="searchResult-Container">
<ul>
<li *ngFor="let stocks of products"
[class.selected]="stocks === selectedStock"
(click)="onSelected(stocks)">
<div class="row searchItem" style="margin:0px;">
<!--search item starts-->
<div class="col-md-10 col-sm-10 col-xs-12">
<div class="row">
<div class="col-md-6 col-sm-6 col-xs-12 hidden">
<label>Item</label>
<span>{{stocks.ItemID}} </span>
</div>
and my TS code is
onSelected(IComboDetails: IComboDetails): void {
this.selectedStock = IComboDetails;
}

Looks like you want to remove all items you click plus
onSelected(comboDetails: IComboDetails): void {
const index = this.products.indexOf(comboDetails);
if (index !== -1) {
this.products.splice(index, 1);
}
}

Related

How to compare two classes with jquery?

I want to compare two classes if they're equal to display the content. I have three btns with three different classes and three other divs with three similar classes to buttons. I want to check if Over the button is equal to over the div,then i want to show the element inside over the div, and hide the other elements,and when i click on the under the button i want to do the same, I have tried with Jquery to compare to first get the class name from the button and get the class name from the div and compare them to each other and then give the active class to the one that i want to show it but it seems that i have something wrong
var className = $(this).attr('class');
var tabContent = $('.tab-content').hasClass(className);
var classNameBtnsName = $(this).hasClass(className);
$('button').click(function () {
if (tabContent === classNameBtnsName) {
$('.tab-content').addClass("active-content");
} else {
$('.tab-content').removeClass("active-content");
}
})
.active-content h1{
display:block;
}
h1{
display:none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="btns-container">
<button class="over">Over</button>
<button class="under">Under</button>
<button class="other">Other</button>
</div>
<div class="tab-content over active-content">
<h1 >Show Over elements</h1>
</div>
<div class="tab-content under">
<h1>Show Under elements</h1>
</div>
<div class="tab-content other">
<h1>Show Other Elements</h1>
</div>
I wouldn't use the class of the buttons to specify which content to toggle. It is better to use a data attribute for that to prevent future developments that add more classes to bug your functionality. Then you can use this data attribute for toggling by removing the active class from all and then adding the class to the element belonging to the clicked button.
$('button.togglebutton').on('click', (e) => {
$('.tab-content').removeClass('active-content');
$('.tab-content.' + $(e.currentTarget).data('active-content')).addClass('active-content');
});
.active-content h1 {
display: block;
}
h1 {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="btns-container">
<button data-active-content="over" class="togglebutton">Over</button>
<button data-active-content="under" class="togglebutton">Under</button>
<button data-active-content="other" class="togglebutton">Other</button>
</div>
<div class="tab-content over active-content">
<h1>Show Over elements</h1>
</div>
<div class="tab-content under">
<h1>Show Under elements</h1>
</div>
<div class="tab-content other">
<h1>Show Other Elements</h1>
</div>
Inside the click handler callback function, remove the active-content class from all .tab-content elements first, and then add it to the one that also has the button's class.
$('.btns-container button').on('click', function() {
$('.tab-content').removeClass('active-content');
$('.tab-content.' + this.className).addClass('active-content');
});
.active-content h1{
display:block;
}
h1{
display:none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="btns-container">
<button class="over">Over</button>
<button class="under">Under</button>
<button class="other">Other</button>
</div>
<div class="tab-content over active-content">
<h1 >Show Over elements</h1>
</div>
<div class="tab-content under">
<h1>Show Under elements</h1>
</div>
<div class="tab-content other">
<h1>Show Other Elements</h1>
</div>
Assuming .tab-content is hidden by default, you can try something like this:
$('button').click(function() {
// Get class from clicked button
var btnClass = $(this).attr('class');
$('.tab-content').each(function() {
// If tab-content has same class as button, show this
if ($(this).hasClass(btnClass)) {
$(this).show();
} else {
$(this).hide();
}
});
});

How to call a container component from within contained component

my landing page component declares in it a header component like so
<div class="container-fluid">
<div class="intro-section">
<div class="background">
//some stuff
</div>
<div class="content">
<app-page-header></app-page-header>
<div class="row">
<div class="col-12 text header mt-3">
Hello World
</div>
<div class="col-12 text-center mt-4 mb-4">
<button class="btn know-more-btn text" (click)="scroll(subscriptions)">Tell me More</button>
</div>
</div>
</div>
</div>
<div #subscriptions></div>
<div id="others" class="otherSection">
//other stuff
</div>
</div>
the scroll function in landing-page.component.ts is
scroll(el: HTMLElement) {
el.scrollIntoView({behavior:"smooth"});
}
I've also tried this
scrolling() {
(document.getElementById('others')).scrollIntoView({behavior:"smooth"});
}
I want to have a button in my app-page-header component that triggers or perform the same action an "scroll(subscriptions)" i.e in the landing page scroll to subscriptions. How can I achieve this?
Create an EventEmitter inside you app-page-header like
#Output() onButtonClicked: EventEmitter<any> = new EventEmitter();
The button in your app-page-header will emit the action to the parent component like:
buttonClicked() {
onButtonClicked.emit();
}
On your landing page add this to call the scroll function whenever the event is emitted.
<app-page-header (onButtonClicked)="scroll(subscriptions)"></app-page-header>

Building Bootstrap template with #foreach from asp.net razor not as expected

I have a json with some objects. Using #foreach from Razor, I want to expose the results on a template, along with some filters that will filter my results.
The problem is that I can't render the template correctly. I want my sidebar/widget to be rendered one time one the right, and the results to be rendered one bellow another, and to look as you'd expect.
CODE:
#{int i = 0;}
#{
var client = new WebClient();
var json = client.DownloadString("http://example.com/raw/a5N8mJ2Y");
var results = Json.Decode(json);
}
<div class="container">
<div class="row">
#foreach (var result in results)
{
i++;
if (i == 2)
{
<!-- Left sidebar goes here -->
<aside id="sidebar" class="col-sm-3">
<section id="filters">
<h3>Filtre</h3>
...
</section>
</aside>
}
<div style="border-style: groove; " class="col-sm-9">
<!-- objects from json go here -->
</div>
}
</div>
</div>
Screenshot:
If you want your sidebar to appear only once, it's pointless being in the foreach loop. It's getting put to the right and pushing the next item down because you're placing it between the results columns.
I think you should set it out so there is one aside element outside of the foreach loop and one column that contains the json items, e.g.
<div class="container">
<div class="row">
<!-- Left sidebar goes here -->
<aside id="sidebar" class="col-sm-3">
<section id="filters">
<h3>Filtre</h3>
...
</section>
</aside>
<div class="col-sm-9">
#foreach (var result in results)
{
<div class="item-result">
<!-- object result here -->
</div>
}
</div>
</div>
</div>
Then just style your .item-result class like:
.item-result{
border-style: groove;
display: block;
margin-bottom: 15px;
}

How float divs to two sides in razor view

I'm trying to view notifications on razor view. I used foreach loop to get the data from the model.I want to display both "invitations" and "Requests" divs on the view like in the two table columns.One invitation down after another invitation.one request down after another request..(in one column all the invitations and requests on the other).. i used css float to do this.. but in the divs get mix in the result..why is that? there are some othaer elements in the view like, nav bar,side bar etc...my code is as follows;
foreach (var item in Model)
{
if (#item.CreatedBy == item.UserId)
{
<div style="float: right; width: 580px;">
<div class="panel panel-info" style="width:500px;margin-right:50px">
×
<div class=" panel-heading">
<h3 class="panel-title">Notification #counter1</h3>
</div>
<div class="panel-body">
<p>Event is created by yourself .Budget of the event is #item.Budget <p>
#if (item.IsAccepted)
{
<p>You have accept the invitation!!!</p>
}
#if (!item.IsAccepted)
{
<p>You haven't accept the invitation yet!!!!</p>
}
#{counter1++;}
</div>
</div>
<br />
</div>
}
else
{
<div style="width: 580px; float: left">
<div class="panel panel-info" style="width:500px;margin-left:250px;">
×
<div class=" panel-heading">
<h3 class="panel-title">Notification #counter2</h3>
</div>
<div class="panel-body">
<p>Event is created by #item.Email .Budget of the event is #item.Budget <p>
#if (item.IsAccepted)
{
<p>You have accept the invitation!!!</p>
}
#if (!item.IsAccepted)
{
<p>You haven't accept the invitation yet!!!!</p>
}
#{counter2++;}
</div>
</div>
<br />
</div>
}
}
What you need is css attributes "clear: right" and "clear: left" for your div's.
However, once you use them you will find next problem - there will be vertical gaps between your div's on the right and left side. That is because you are placing new div's right into body element of html page in your foreach loop. To make it right, you should first create two containers (divs) to which you should respectively add your divs containing data.
Unfortunately, with your current implementation you would have to iterate over your Model twice - once to fill up the right container with divs, and then once again to fill up the left container.
A better approach would be to create a ViewModel containing two collectios of objects which you are currently using, e.g.:
public class MyViewModel
{
public IList<MyModel> Invitations { get; set; }
public IList<MyModel> Requests { get; set; }
}
and use it as your View's model
#model MyApplication.Models.MyViewModel.
With this approach, you also remove some logic from the view, which is a good thing.
Here is an updated code for your view using the ViewModel as View's model:
#model MvcApplication1.Controllers.MyViewModel
#{
int counter1 = 0, counter2 = 0;
}
<div style="float: right; width: 580px; clear:right">
<span>Invitations</span>
#foreach (var item in #Model.Invitations)
{
if (#item.CreatedBy == item.UserId)
{
<div>
<div class="panel panel-info">
×
<div class=" panel-heading">
<h3 class="panel-title">Notification #counter1</h3>
</div>
<div class="panel-body">
<p>Event is created by yourself .Budget of the event is #item.Budget <p>
#if (item.IsAccepted)
{
<p>You have accept the invitation!!!</p>
}
else
{
<p>You haven't accept the invitation yet!!!!</p>
}
#{counter1++;}
</div>
</div>
<br />
</div>
}
}
</div>
<div style="float: left; width: 580px; clear:left">
<span>Requests</span>
#foreach (var item in #Model.Requests)
{
<div>
<div class="panel panel-info">
×
<div class=" panel-heading">
<h3 class="panel-title">Notification #counter2</h3>
</div>
<div class="panel-body">
<p>Event is created by #item.Email .Budget of the event is #item.Budget <p>
#if (item.IsAccepted)
{
<p>You have accept the invitation!!!</p>
}
else
{
<p>You haven't accept the invitation yet!!!!</p>
}
#{counter2++;}
</div>
</div>
<br />
</div>
}
</div>
Good luck :)
Edit: a quick lookup to how the page looks after using provided solution:
https://jsfiddle.net/nh8Ls531/

Bootstrap Responsive Product Grid

I am building a product grid built upon AngularJS data - where there will be images and product details (text)
The text sometimes extends to the 2nd line, causing havoc.
Here is my code:
<div class="row">
<div data-ng-repeat="s in Results">
<div class="col-xs-4">
<a href="#" class="thumbnail">
<div>
<img ng-src="{{s.ProductImage}}" class="img-responsive">
</div>
<div>
{{s.Store}} {{s.Category}} {{s.ProductName}}
</div>
</a>
</div>
<div class="clearfix visible-xs-block"></div>
</div>
</div>
This is what it looks like:
How do I fix it so that <div>s all have the same height?
I tried to look online for solutions, but I think I am 50% there. Please help.
Note: I Don't want to hide content.
This is what I ended up doing for anyone who stumbles on this again in the future.
Javascript
function ResizeToLargestElement(element) {
var maxHeight = -1;
if ($(element).length > 0) {
$(element).each(function () {
maxHeight = maxHeight > $(this).height() ? maxHeight : $(this).height();
});
$(element).each(function () {
$(this).height(maxHeight);
});
}
}
Without AngularJS
For those who aren't using AngularJS, just call ResizeToLargestElement() when data changes or the window is resized using
$(window).resize(function() {
ResizeToLargestElement('.AutoResizeToLargestElement');
});`
With AngularJS
The idea is to call the ResizeToLargestElement() function whenever $scope.Results changes or when the window resizes.
To know when $scope.Results changed is easy, but to know when elements (that are bound to it) finished rendering is not easy. To do that, you need a AngularJS directive.
To know when the window re-sizes, use angular.element($window).on('resize', function () {...});
HTML
<div class="row">
<div data-ng-repeat="s in Results" data-ng-repeat-finished> <!--ADDED Directive-->
<div class="col-xs-4">
<a href="#" class="thumbnail AutoResizeToLargestElement"> <!--ADDED Class-->
<div>
<img ng-src="{{s.ProductImage}}" class="img-responsive">
</div>
<div>
{{s.Store}} {{s.Category}} {{s.ProductName}}
</div>
</a>
</div>
<!--REMOVED clearfix-->
</div>
</div>
MyDirectives.js
angular.module('myApp').directive('ngRepeatFinished', function ($timeout) {
return {
restrict: 'A',
link: function (scope, element, attr) {
if (scope.$last === true) {
$timeout(function () {
scope.$emit('ngRepeatFinished');
});
}
}
}
});
mycontroller.js
$scope.$on('ngRepeatFinished', function (ngRepeatFinishedEvent) {
ResizeToLargestElement(".AutoResizeToLargestElement");
});
angular.element($window).on('resize', function () {
ResizeToLargestElement(".AutoResizeToLargestElement");
});
Note: this requires you to include $window in the AngularJS dependency list.
I.E. angular.module('myApp').controller('....', ['...., '$window', ....]);
If you want to keep the height of each product dynamic, you will need to split the results into columns. And then use ng-if to put the right items in the right column. Every 3rd item will go into the same column. To set them to different columns, just reduce the $index by 1 for each extra column.
<div class="row">
<div class="col-xs-4">
<div ng-repeat="s in Results"> <a href="#" class="thumbnail" ng-if="$index%3==0">
<div>
<img ng-src="{{s.ProductImage}}" class="img-responsive" />
</div>
<div>{{s.Store}} {{s.Category}} {{s.ProductName}}</div>
</a>
<div class="clearfix visible-xs-block"></div>
</div>
</div>
<div class="col-xs-4">
<div ng-repeat="s in Results"> <a href="#" class="thumbnail" ng-if="($index-1)%3==0">
<div>
<img ng-src="{{s.ProductImage}}" class="img-responsive" />
</div>
<div>{{s.Store}} {{s.Category}} {{s.ProductName}}</div>
</a>
<div class="clearfix visible-xs-block"></div>
</div>
</div>
<div class="col-xs-4">
<div ng-repeat="s in Results"> <a href="#" class="thumbnail" ng-if="($index-2)%3==0">
<div>
<img ng-src="{{s.ProductImage}}" class="img-responsive" />
</div>
<div>{{s.Store}} {{s.Category}} {{s.ProductName}}</div>
</a>
<div class="clearfix visible-xs-block"></div>
</div>
</div>
</div>
You can manually restrict the height of the div and use an overflow. Use something like
<div class="col-xs-4" style="height:200px; overflow: auto;">Content</div>
Or, you could always use a responsive table (<table class="table table-responsive">) for your layout.
The best solution for this problem is to add clearfix class to hidden divs for earch size of viewport. for example:
Large size: i want 6 columns (large desktops)
Medium size: i want 4 columns (Desktops)
Tablets: i want 3 coumns
phones: i want 2 columns
so i have the products list:
<?php $count=1; foreach($productList as $product) : ?>
<div class="item col-xs-6 col-sm-4 col-md-3 col-lg-2">
Picture and description
</div><!-- /item -->
<?php if( ($count%2)==0) {?><div class="clearfix visible-xs-block"></div><?php }?>
<?php if( ($count%3)==0) {?><div class="clearfix visible-sm-block"></div><?php }?>
<?php if( ($count%4)==0) {?><div class="clearfix visible-md-block"></div><?php }?>
<?php if( ($count%6)==0) {?><div class="clearfix visible-lg-block"></div><?php }?>
<?php $count++; endforeach?>