Select inside ng-repeat with ng-options and ng-model - html

Good Morning,
Hope everyone had a great Easter,
Before I begin, I want to point out this is being developed in ServiceNow Orlando release, it uses AngularJS 1.6.10
I'm stuck on a tricky piece of code I can't get right, I'm using an ng-repeat to build out a catalog of hardware devices, in this case its Laptops, we have added a button which quickly allows people to add the device to the cart, we now want to add a quantity field so that multiple devices can be added at the same time, I got it working but AngularJS adds in an empty cell at the beginning, I need to get it to default to 1, I did get it to do this but it broke the cart experience as every item added to the cart is a 1 no matter what quantity is selected.
so this is most of the html code which also includes the ng-repeat that builds out the hardware devices, I am using an ng-options that everyone seems to recommend, been reading a lot in Stack Overflow.
The problem is the ng-model, as this is set to $scope.items[0] it never gets updated, I have been looking at getterSetter but very much going over my head at the moment, can't get it to work.
<div class="col-sm-6 col-md-4 funky-show-hide" ng-show="selectedCat==item.categoryBelongTo" ng-repeat="item in data.items track by $index">
<div class="panel panel- b" >
<a target="" ng-href="" ng-click="onClick($event, item)" class="panel-body block">
<div class="overflow-100">
<h4 class="m-t-none m-b-xs hrline"><span ng-if="item.content_type == 'external'"> <i ng-if="data.isDownloadable.indexOf(item.sys_id) ==-1" class="fa fa-external-link-square" aria-hidden="true" style="color: #498fcc;"></i><i ng-if="data.isDownloadable.indexOf(item.sys_id) >-1" class="fa fa-download" aria-hidden="true" style="color: #498fcc;"></i></span></h4>
<img ng-src="" ng-if="item.picture" class="m-r-sm m-b-sm item-image pull-left" />
<div class="text-muted item-short-desc"></div>
</div>
</a>
<div class="panel-footer" >
<span ng-if="item.u_show_price == 'true'" class="pull-right item-price font-bold"></span>
<button ng-if="item.u_show_add_to_cart_button == 'true' " name="submit" ng-disabled="submitted" ng-click="triggerAddToCart(item.sys_id, selected.label)" class="btn btn-primary">${Add to Cart}</button>
<select ng-if="item.u_show_quantity_button == 'true'"
name="Quantity"
id="quantity"
ng-disabled="submitted"
ng-model="selected"
class="form-control quantity-selector"
data-toggle="tooltip"
tooltip-top="true"
data-original-title="${Quantity}"
ng-options="item as item.label for item in items track by item.id">
</select>
</div>
</div>
</div>
Controller:
$scope.items = [{
id: 1,
label: '1'
}, {
id: 2,
label: '2'
}, {
id: 3,
label: '3'
}];
$scope.selected = $scope.items[0];
What it all looks like:
So I have selected "3" on the Performance PC Laptop but if you look at the console log on the right, you can see the value added is 1.
Picture to display value added to cart
Shame really, I was happy with the empty cell but its what the client would like, I know I can update the empty cell with some text but they would really like it to default to 1.
Any suggests and I would be grateful,
Bored Panda

Replacing the ng-if with ng-show resolved my problem, days lost trying to figure this out, also developed a simpler solution with number increment
Code Here:
<input type="number" value="1" min="1" max="20" step="1" ng-model="items_increment" title="Quantity" ng-show="item.u_show_quantity_button == 'true'"/>
$scope.items_increment = 1;
Hope it helps another person.

Related

How to hide something when no search result found in angular

In my homepage I have a search bar and a list of user favorite cards. Only If there is no favorited cards on the initial browser load and when a user removed all their favorite cards then it'll show a banner "Add a favorite...".
The problem I have right now is the banner is displaying when I search something on the search-bar and found no favorited card. How do I fix that?. I don't want to show my banner if there is no search result found.
If I do favorites.size == 0 instead then the banner is not showing up at all when browser load or user removed all their cards.
<div class="input">
<form class="search-form">
<input #searchValue id="input-field" class="input-field" type="search"
name="insightSearchFilter" (ngModelChange)="filterChanged($event)" [formControl]="inputCtrl"/>
<p class="hint" *ngIf="inputCtrl.value">
<strong> {{ favorites?.length }} Search Result for </strong><em>"{{ inputCtrl?.value }}".</em>
<strong> The Results listed below are exact matches for your query.</strong>
</p>
</form>
</div>
<div *ngIf="favorites">
<div *ngIf="favorites.length > 0">
<app-card-list [cards]="favorites"></app-card-list>
</div>
<div *ngIf="favorites.length == 0" class="empty-faves-container">
<div class="add-faves-container">
<div class="add-faves-ico"></div>
<div class="text">Add a Favorite</div>
</div>
</div>
</div>
Since you are filtering this.favorites in filterChanged methods. You should apply check for search text also along with length check.
like
(favorites.length == 0 && !(inputCtrl.value))

How do I get a button used on multiple card containers to only affect one container at a time?

I am currently working on a web application using angular and angular material. The page in question holds several profiles each with a button that when clicked removes the information currently showing and replaces it with the rest of the profile information. The issue is that when I click this button on one profile it does this information flip on all the profiles at once. I need help figuring out how to have the button only affect the profile it is associated with.
I am still relatively new to coding, so I've mainly been doing research on advice on how to approach this particular situation, but nothing I've found so far has worked.
<mat-card class="bpBuddyCont" *ngFor= "let profile of profileList">
<div>
<ul class="bpBuddies">
<li class="li2">
<div *ngIf="!showHiddenInfo">
<mat-card-title class="specifics">{{profile.dogName}}</mat-card-title>
<mat-card-subtitle class="subtitle">Owner ~ {{profile.ownerFirstName}}</mat-card-subtitle>
<mat-card-subtitle>Member Since {{profile.yearJoined}}</mat-card-subtitle>
</div>
<div class="column4" *ngIf="showHiddenInfo">
<span class="details4">Additional Notes: </span>
<span class="details3">{{profile.additionalNotes}}</span>
</div>
</div>
<button mat-button color="primary" class="btn" (click)="showHiddenInfo = !showHiddenInfo">{{showHiddenInfo ? 'Back' : 'More...'}}</button>
</li>
</ul>
</div>
</mat-card>
You can extend the profile object with
profile.showHiddenInfo and set it as false initially.
For this in your js(most probably the component file) after getting profileList,
profileList.forEach((profile, index) => {
angular.extend(profile, {showHiddenInfo: false});
//not sure about this angular.extend but you need to extend your object here
});
Now when the button is clicked replace showHiddenInfo, i.e.
profile.showHiddenInfo = !profile.showHiddenInfo;
And Replace
*ngIf="showHiddenInfo"
with
*ngIf="profile.showHiddenInfo"
You can do this using one boolean variable for each object, as profile.isExpanded and on click change it as like:
(click)="profile.isExpanded = !profile.isExpanded"
HTML Code:
<mat-card class="bpBuddyCont" *ngFor="let profile of profileList">
<div>
<ul class="bpBuddies">
<li class="li2">
<div *ngIf="!profile.isExpanded">
<mat-card-title class="specifics">{{profile.dogName}}</mat-card-title>
<mat-card-subtitle class="subtitle">Owner ~ {{profile.ownerFirstName}}</mat-card-subtitle>
<mat-card-subtitle>Member Since {{profile.yearJoined}}</mat-card-subtitle>
</div>
<div class="column4" *ngIf="profile.isExpanded">
<span class="details4">Additional Notes: </span>
<span class="details3">{{profile.additionalNotes}}</span>
</div>
<button mat-button color="primary" class="btn" (click)="profile.isExpanded = !profile.isExpanded">{{profile.isExpanded ? 'Back' : 'More...'}}</button>
</li>
</ul>
</div>
</mat-card>
No change in TS file.
WORKING STACKBLITZ

How to know the length of filtered data after an already filter in angular4

I have two functionalities of a text-box. First, it displays a filtered data on enter press or pressing on the search button and second filter happens if you type anything in the textbox and accordingly it filters and displays the result from the filtered data result.
Error is -
Parser Error: Bindings cannot contain assignments at column 32 in
[arrayCount1 of ctrl.filtered = (result| filter: query)]
I understood the error but how to get the number from already filtered data count.Do i have to do something in .ts file.
The code for it is -
transaction.component.html
<td style="width:50%">
<input class="form-control" id="input1-group1 "
style="margin-top:20px" type="text" name="search"
placeholder="Enter Search Text"
[(ngModel)]="filterdata"
(keyup.enter)="searchByText(filterdata)">
</td>
<td style="width:50%">
<button type="submit" class="input-group-addon"
style="margin-left:0px;width:65px;margin-top:20px" id="faIcon"
(click)="searchByText(filterdata)" >
<i class="fa fa-search "></i>
</button>
</td>
....//code
<div class="panel panel-default panel-transparent">
<div class="panel-heading text-left">
<h2> Transaction </h2>
<label *ngIf="toShowCount" id="arrayCountId"> Number of searched
data : {{arrayCount}}</label>
<ul>
<li *ngFor = "arrayCount1 of ctrl.filtered = (result| filter:
query)"
id="arrayCountId">Number of filtered search data : {{arrayCount1}}
</li>
</ul>
</div>
</div>
transaction.component.ts
this.http.post("http:...)
.map(result => this.result = result.json())
.subscribe((res: Response) => {
this.records = res;
this.toShowCount =true;
this.arrayCount = this.result.length;
console.log("ArrayCount = " , this.arrayCount)
I have a link to a similar question but in AngularJS :
How to display length of filtered ng-repeat data
You are mixing Angular with Angular JS. We use pipes instead of filter in Angular.
In order to display the result of filtered array result, you just need to check the length property.
<div class="panel panel-default panel-transparent">
<div class="panel-heading text-left">
<h2> Transaction </h2>
<label *ngIf="toShowCount" id="arrayCountId"> Number of searched
data : {{arrayCount}}</label>
<ul>
<li *ngFor= "let count of (result| pipe:
'pipeName')"
id="arrayCountId">
Number of filtered search data : <span [textContent]="(result| pipe:'pipeName').length"> </span>
</li>
</ul>
</div>
</div>

Knockout Clone Whole Item In foreach

I am trying to clone elements when clicking a button. I was trying to use ko.toJS. On page load it works fine, but when I want clone the items, it is unable to bind the items (like, value, Text, etc.).
Here is the HTML:
<div class="stockItems-inner" data-bind="foreach: StockItems">
<div data-bind="if: Type=='Input'">
<div class="stock_container_input">
<input type="text" data-bind="value: Value" />
</div>
</div>
<div data-bind="if: Type=='Radio'">
<div class="stock_container_control">
<div data-bind="foreach: Options">
<div class="stockLbl">
<input type="radio" data-bind="text: Text, checked:$parent.Value, attr:{'id':Id, 'name': $parent.Text, 'value': Value}" />
<label data-bind="attr:{'for':Id}, text: Text"></label>
</div>
</div>
</div>
</div>
</div>
<div class="addItem">
<button type="button" data-bind="click: CloneItem"><img src="images/add.png" alt="" /></button>
</div>
The View Model:
ConfigurationStockViewModel = function() {
var self = this;
this.StockItems = ko.observableArray();
this.ApplyData = function(data){
self.StockItems(data.Items);
}
this.CloneItem = function(StockItems){
self.StockItems.push(ko.toJS(StockItems));
};
};
When clicking the button, an error is thrown: Unable to process binding. I am using JSON data for binding.
Not exactly sure what end result you want without working code, but sounds like you want to clone the last item in array and add to array?
If so, I think you have an error - your add button click binding will never pass anything to the function you defined, since it is outside the foreach. You need something like this:
this.CloneItem = function() {
var toClone = self.StockItems()[self.StockItems().length - 1]
self.StockItems.push(toClone);
};
Here is a simplified example without radio buttons, etc:
http://jsfiddle.net/5J47L/

jQuery live filter/search

I'm building an icon library where the user on the front end (submitting a form) can select an icon. I managed to get everything working as far as the selection process. Now, the final product will have over 400 icons, and i wanted to add a search (ajax, i guess) or autocomplete input where the user can type a couple of letters and it filter's out those icons.
They search will be filtering out some with a class that has the prefix "icon-", so the search term would be whatever is after that prefix. (i.e: icon-TWIITER, icon-FACEBOOK, etc).
I started on jsFiddle here: http://jsfiddle.net/yQMvh/28/
an example would be something like this :
http://anthonybush.com/projects/jquery_fast_live_filter/demo/
http://cheeaun.github.io/jquery.livefilter/
I'm trying to stay away from jQuery plugins and try and figure this out before i resort to that. I'm using wordpress as the backend of the website.
as soon as the user types, it's already sorting out the icons that pertain to the input value.
My HTML Markup:
<div class="iconDisplay">Display's selected icon</div>
<span id="selectedIcon" class="selected-icon" style="display:none"></span>
<button id="selectIconButton">Select Icon</button>
<div id="iconSelector" class="icon-list">
<div id="iconSearch">
<label for="icon-search">Search Icon: </label>
<input type="text" name="icon-search" value="">
</div>
<span class="icon-icon1"></span>
<span class="icon-icon2"></span>
<span class="icon-icon3"></span>
<span class="icon-icon4"></span>
<span class="icon-icon5"></span>
<span class="icon-icon6"></span>
<span class="icon-icon7"></span>
<span class="icon-icon8"></span>
</div>
JS:
var iconVal = $(".icon_field").val();
$('#selectedIcon').addClass(iconVal);
$("#selectIconButton").click(function () {
$("#iconSelector").fadeToggle();
});
$("#iconSelector span").click(function () {
selectIcon($(this));
});
function selectIcon(e) {
var selection = e.attr('class');
$(".icon_field").val(selection);
$("#iconSelector").hide();
$('#selectedIcon').removeClass();
$('#selectedIcon').addClass(selection).show();
return;
}
Made an update on your jsfiddle jsfiddle.net/yQMvh/30 Just enter the classname e.g. icon-icon1 and all icons without icon-icon1 gets hidden