Angularjs ng-repeat does not update after changing $scope variable - javascript

Hi I am new to Angularjs. I am changing the $scope variable on dropdown list selection. that scope variable is used for ng-repeat on div.
html code:
<div class="col-md-6" ng-repeat="model in FilteredModels | filter:{ModelText : '!All models'}:true">
<div class="well">
<div class="media">
<div class="media-object small"><i class="pp-car"></i></div>
<div class="media-body">
<div class="text-box">
<h3>{{model.ModelText}}</h3><span class="hr-small"></span>
</div>
<div class="dashboard-control clearfix">
<div class="simple-metric text-left sub-metric">
<div class="metric-title">Satisfaction score</div>
<div class="metric-number text-red">{{model.SatisfactionAvg | number:2}}</div>
</div>
<div class="simple-metric text-left sub-metric">
<div class="metric-title">Total interviews</div>
<div class="metric-number">{{model.TotalInterviews}}</div>
</div>
</div>
<ul class="list-standard">
<li> View interviews</li>
</ul>
</div>
</div>
</div>
</div>
angularjs code :
function filtermodelbyId() {
$scope.FilteredModels = [];
dataFactory.getModelIdByFilter($scope.region, $scope.subregion).success($scope.handleSuccess).then(function (result) {
$scope.FilteredModelIds = result.data;
});
if ($scope.FilteredModelIds != null && $scope.FilteredModelIds.length > 0) {
for (var j = $scope.FilteredModelIds.length - 1; j >= 0; j--) {
for (var i = $scope.models.length - 1; i >= 0; i--) {
if ($scope.models[i].ModelId == $scope.FilteredModelIds[j]) {
$scope.FilteredModels.push($scope.models[i]);
}
}
}
}
}
On change of dropdown list this filtermodelbyId() function gets call and i am pushing new values but this gets reflected after the second change on dropdown list.
is there any better way to represent this.
Thanks.

Seems like you are not using $http in dataFactory.getModelIdByFilter .
try using
$scope.$apply(function(){
$scope.FilteredModelIds = result.data;
});
Or else you can use angular services to load data (Assuming that you are using jquery ajax.)

You need to write if after $scope.FilteredModelIds is set
dataFactory.getModelIdByFilter($scope.region, $scope.subregion).success($scope.handleSuccess).then(function (result) {
$scope.FilteredModelIds = result.data;
if ($scope.FilteredModelIds != null && $scope.FilteredModelIds.length > 0) {
for (var j = $scope.FilteredModelIds.length - 1; j >= 0; j--) {
for (var i = $scope.models.length - 1; i >= 0; i--) {
if ($scope.models[i].ModelId == $scope.FilteredModelIds[j]) {
$scope.FilteredModels.push($scope.models[i]);
}
}
}
}
});

Just of quick wild guess:
function filtermodelbyId() {
$scope.FilteredModels = [];
dataFactory.getModelIdByFilter($scope.region, $scope.subregion).success($scope.handleSuccess).then(function (result) {
$scope.FilteredModelIds = result.data;
if ($scope.FilteredModelIds != null && $scope.FilteredModelIds.length > 0) {
for (var j = $scope.FilteredModelIds.length - 1; j >= 0; j--) {
for (var i = $scope.models.length - 1; i >= 0; i--) {
if ($scope.models[i].ModelId == $scope.FilteredModelIds[j]) {
$scope.FilteredModels.push($scope.models[i]);
}
}
}
}
});
}
Change the model array in the callback.

Related

Filter function in JavaScript

I'm currently working on an e-commerce site and I'm stuck on the search page, especially when filtering the products.
**
This is the HTML code for the product card:**
<div class="product-seller-item" data-brand="Louis Vuitton" data-category="Helmets">
<div class="product-page-seller-item-header">
<img src="/Images/user.png" alt="User profile image">
<p>citygirl1996</p>
</div>
<img class="product-page-seller-item-body-image" src="/Images/Products/product1.png" alt="">
<div class="product-page-seller-item-footer">
<div class="product-page-seller-item-footer-flex">
<p>£15.00</p>
</div>
<p class="product-page-seller-item-footer-description">Juicy Couture</p>
</div>
</div>
And this is the code for the checkbox:
<label class="container">Helmets
<input type="checkbox" value="Helmets">
<span class="checkmark"></span>
</label>
<label class="container">Louis Vuitton
<input type="checkbox" value="Louis Vuitton">
<span class="checkmark"></span>
</label>
And this is the code for JavaScript:
const checkboxes = document.querySelectorAll('input[type="checkbox"]');
const products = document.querySelectorAll('.product-seller-item');
for (let i = 0; i < checkboxes.length; i++) {
checkboxes[i].addEventListener('change', function () {
for (let j = 0; j < products.length; j++) {
let productVisible = false;
for (let k = 0; k < checkboxes.length; k++) {
if (checkboxes[k].checked && products[j].dataset.category === checkboxes[k].value) {
productVisible = true;
break;
} else if (checkboxes[k].checked && products[j].dataset.brand
&& products[j].dataset.brand === checkboxes[k].parentElement.textContent.trim()) {
productVisible = true;
break;
}
}
if (productVisible) {
products[j].style.display = 'block';
} else {
products[j].style.display = 'none';
}
}
});
}
The problem is as follows, when I select the Helmets category, it shows me all of them, everything works perfectly, but when I select the brand, it doesn't hide the product that doesn't match.
If the products have a category you can use filtermethod, that will return you a new array with the elements that have this conditions. For example:
const products = document.querySelectorAll('.products'):
const categories = document.querySelectorAll('input[type=checkbox]');
const filteredProducts
= products.filter(product => product.category == categories.checked);

.style.display = "block" don't work any idea how to fix this?

hi happy new year for all I have this problem with .style it shows this error in the console
Uncaught TypeError: Cannot read property '0' of undefined
at HTMLImageElement.show (Slideshowmodal.js:15)
do you have any idea what I am messing up ?
initmodal();
function initmodal()
{
modalclick = document.getElementsByClassName('Slideshowimg');
for (i = 0; i < modalclick.length; i++)
{
modalclick[i].onclick = function show()
{
Modalarts = this.parentNode.parentNode.getElementsByClassName("modalria");
for (j = 0; j < this.parentNode.children.length; j++)
{
this.Modalarts[j].style.display = "block";
if (this.parentNode.children[j] == this)
{
index = j;
}
}
this.Modalarts[index].style.display = "block";
}
}
};
<div id="myModalriaArt" class="modalria">
<span class="closer cursor" onclick="closeModal()">×</span>
<div class="modal-content-ria">
<img class="Slideshowimgmodal" src="./imgs/Riaarts/1/Main1.jpg"
style="width:100%" alt="You left a big holedasdasda 30x40">
<img class="Slideshowimgmodal" src="./imgs/Riaarts/1/RA1Z2.jpg"
style="width:100%" alt="You left a big hole 30x40">
<!-- -->
</div>
</div>
initmodal();
function initmodal() {
modalclick = document.getElementsByClassName('Slideshowimg');
for (i = 0; i < modalclick.length; i++) {
modalclick[i].onclick = function show() {
Modalarts = this.parentNode.parentNode.getElementsByClassName("modalria");
for (j = 0; j < this.parentNode.children.length; j++) {
this.Modalarts[j].style.display = "block";
if (this.parentNode.children[j] == this) {
index = j;
}
}
this.Modalarts[index].style.display = "block";
}
}
};
const cross = document.getElementById('cross')
.addEventListener('click', () => {
document.getElementById("myModalriaArt").style.display= "none";
},false);
<div id="myModalriaArt" class="modalria">
<span id="cross" class="closer cursor">×</span>
<div class="modal-content-ria">
<img class="Slideshowimgmodal" src="./imgs/Riaarts/1/Main1.jpg" style="width:100%"
alt="You left a big holedasdasda 30x40">
<img class="Slideshowimgmodal" src="./imgs/Riaarts/1/RA1Z2.jpg" style="width:100%"
alt="You left a big hole 30x40">
</div>
</div>
Modalarts is defined as a local variable, so no need for "this" in front.

Price filter (min and max price) with a dropdown menu asp.net core

I'm trying to filter through prices using javascript and asp.net core, and I've come up with a heap of javascript which doesn't really work.
There has to be an easier way, using jquery or with c#?
If anyone has any suggestions it would be greatly appreciated!
Price Filter
<p>Sort By Price: </p>
<select id="sort" onChange="OnSelectedIndexChange()">
<option value="all">All</option>
<option value="1">$0 - $50</option>
<option value="2">$51 - $100</option>
<option value="3">$101 - $150</option>
<option value="4">$151 + </option>
</select>
<div class="row">
#{
foreach (var item in Model.Products)
{
if (item.CategoryId == Model.CategoryId)
{
<div class="card h-100" id="hamper">
<p id="price">$#item.Price</p>
</div>
}
}
}
</div>
</div>
<!-- Javascript -->
<script type="text/javascript">
var prices = [];
#foreach(var item in Model.Products)
{
#:prices.push(#item.Price)
}
function OnSelectedIndexChange() {
if (document.getElementById('sort').value == "all") {
document.getElementById("hamper").style.display = "block";
} else if (document.getElementById('sort').value == "1") {
for (var i = 0; i < prices.length; i++) {
if (prices[i] >= 0 && prices[i] <= 50 ) {
document.getElementById("hamper").style.display = "block";
} else {
document.getElementById("hamper").style.display = "none";
}
}
} else if (document.getElementById('sort').value == "2") {
for (var i = 0; i < prices.length; i++) {
if (prices[i] >= 51 && prices[i] <= 100) {
document.getElementById("hamper").style.display = "block";
} else {
document.getElementById("hamper").style.display = "none";
}
}
} else if (document.getElementById('sort').value == "3") {
for (var i = 0; i < prices.length; i++) {
if (prices[i] >= 101 && prices[i] <= 150) {
document.getElementById("hamper").style.display = "block";
} else {
document.getElementById("hamper").style.display = "none";
}
}
} else if (document.getElementById('sort').value == "4") {
for (var i = 0; i < prices.length; i++) {
if (prices[i] >= 150) {
document.getElementById("hamper").style.display = "block";
} else {
document.getElementById("hamper").style.display = "none";
}
}
}
}
</script>
There are multiple ways to handle it, in both client side and server side.
Here is a quick sample to do the filtering on client side.
First, add a data attribute to each option in the select to represent the corresponding price range. You may keep the value in this format "lowerRange:upperRange"
<select id="sort">
<option data-price="0:#Int32.MaxValue" value="all">All</option>
<option data-price="0:50" value="1">$0 - $50</option>
<option data-price="51:100" value="2">$51 - $100</option>
<option data-price="101:1000" value="3">$101 - 1000</option>
<option data-price="1001:#Int32.MaxValue" value="4">1001 + </option>
</select>
Now when you render each, card, give it a data attribute for storing the price (data-productprice)
<div class="row" id="my-products">
#foreach (var item in Model.Products.Where(a=>CategoryId==Model.CategoryId))
{
<div class="card h-100" data-productprice="#item.Price">
<span>#item.Name</span>
<span>#item.Price</span>
</div>
}
</div>
Now when user make a selection in the sort dropdown, get the data attribute of the selected option, read the lower and upper range, filter the card div's which has a productprice data attribute value which is falling in that range.
$(function () {
var $cards = $("#my-products").find("[data-productprice]");
$("#sort").change(function () {
var t = $(this).find(':selected').data('price');
var a = t.split(':');
var l = parseFloat(a[0]);
var u = parseFloat(a[1]);
$.each($cards, function (a, b) {
var p = parseFloat($(b).data("productprice"));
if (p >= l && p <= u) {
$(b).show();
} else {
$(b).hide();
}
});
});
});
As i mentioned, this is just one way of doing it, you can do the filtering on server side as well (which is something i might prefer).In that approach, you make an ajax call in the change event where you will send the lower and upper range (l and u) and let the server do a filtering based on the price range and return the partial view markup for only those items. When the ajax response comes back, you will replace the HTML of the my-products div.
$(function () {
$("#sort").change(function () {
var t = $(this).find(':selected').data('price');
var a = t.split(':');
var l = parseFloat(a[0]);
var u = parseFloat(a[1]);
var urlForFilteredResults = "/Products/List?priceFrom="+l+"&priceTo="+r;
// Add other filter criteria as needed
$("#my-products").load(urlForFilteredResults);
});
});
Assuming your List action method accepts the params and return a partial view result
I see in your code you are setting the same id value ( id="hamper") for all the cards inside the loop. That is invalid HTML. Your Id's should be unique in a document.

append method is not working in for loop

I have multiple json object and each object have multiple same, For example:
A->
- A1
-A1A
-A1A
- A2
-A2A
-A2A
- A3
-A3A
-A3A
I have tired to execute in below code but it's not working. Can you please suggest me what is the issue in my code?
subscriptionbarMyData = JSON.parse(window.localStorage.getItem('subscriptionBarJson'));
$('.total-month-cost-product-header-names').text('').addClass('hidden');
for (var key in subscriptionbarMyData) {
if (subscriptionbarMyData.hasOwnProperty(key)) {
var val = subscriptionbarMyData[key];
$('.total-month-cost-product-header')
.find('.total-month-cost-product-header-names')
.removeClass('hidden')
.addClass('show')
.text(val.Name + val.ProductPrice);
var addonvalue = subscriptionbarMyData[key]["Add-on"];
for (var keyval in addonvalue) {
if (addonvalue != undefined) {
var TotalOneCostProduct = $('.total-month-cost-product-items').text('');
for (var keyval in addonvalue) {
// var dataValues = addonvalue[keyval].Name;
$('.total-month-cost-product-header-names')
.text(addonvalue[keyval].Name)
.appendTo(TotalOneCostProduct);
}
}
}
}
}
<div class="summary-block">
<div class="total-month-cost-summary">
<div class="total-month-cost-product-header">
<div class="total-month-cost-product-header-names"></div>
<div class="total-month-cost-product-header-price"></div>
</div>
<div class="total-month-cost-product-items">
<div class="total-month-cost-product-item-names"></div>
<div class="total-month-cost-product-item-price"></div>
</div>
</div>
</div>

Angular : Display data item stored in an array one by one

I've a simple situation, where I've a bunch of data stored in an array.
I want to display the array in html view, one by one, when the next/prev buttons are clicked.
I followed this : How to show item from json Array one by one in Angular JS
However, My code doesn't seem to work.
Code :
/**
* Created by PBC on 5/21/2016.
*/
var solver = angular.module('solver', []);
solver.controller('data', data);
function data($scope, $http){
$scope.Type = "";
$scope.qlist = [];
$scope.alist = [];
$scope.idx = 0;
$scope.ans = "";
$scope.q = "";
var config = {
headers : {
'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8;'
}
};
var data = $.param({
_Down_Questions:localStorage.getItem('prb')
});
$http.post("../Php/download_questions.php", data, config).then
(
//Success Callback
function (res) {
$scope.Type = res.data.Type;
if ($scope.Type == 'Objective'){
for(var i = 0; i < res.data.Data.length; i++){
var data = {Q:res.data.Data[i]["Q"], A:res.data.Data[i]["A"]};
$scope.qlist[i] = data;
}
}
else{
for(var i = 0; i < res.data.Data.length; i++){
var data = {Q:res.data.Data[i]["Q"], A:res.data.Data[i]["A"], O:res.data.Data[i]["O"]};
$scope.qlist.push[i] = data;
}
}
},
//Error Callback
function () {
$scope.registrationResponse = "";
swal("Request couldn't be sent!", "", "error");
}
);
$scope.next = function () {
if ($scope.idx < res.data.Data.length){
$scope.alist[$scope.idx] = $scope.ans;
$scope.idx += 1;
$scope.ans = null;
}
};
$scope.prev = function () {
if ($scope.idx > 0){
$scope.idx -= 1;
ans = $scope.alist[$scope.idx];
}
};
}
using this, in the html as :
<div data-ng-controller="data">
<div style="display: table;margin: 0 auto; width: 30%">
<div class="row container" style="margin-top: 50%">
<div class="col l12" data-ng-repeat="q in qlist track by $index" data-ng-show="$index == idx">
{{q[idx]["Q"]}}
</div>
<input placeholder="Answer" data-ng-model="ans" type="text" class="validate center">
<div class="row" style="display: table;margin: 0 auto; width: 100%">
<a class="waves-effect waves-light btn" data-ng-click="next()" style="display: table;margin: 0 auto; width: 50%">Next</a><br>
<a class="waves-effect waves-light btn" data-ng-click="prev()" style="display: table;margin: 0 auto; width: 50%">Previous</a>
</div>
</div>
</div>
</div>
What am I doing wrong ?
I've found the mistakes:
1)
{{q[idx]["Q"]}}
should be
{{q["Q"]}}
2)
$scope.next = function () {
if ($scope.idx < res.data.Data.length){
$scope.alist[$scope.idx] = $scope.ans;
$scope.idx += 1;
$scope.ans = null;
}
};
Here, the condition was wrong :
it should be,
if ($scope.idx < $scope.qlist.length){

Categories

Resources