Using ng-class from a nested ng-repeat - javascript

I have a nested ng-repeat list, and I want to add a class to the parent one when any item from the nested list is modified.
It looks like this:
<div ng-repeat="pa in products" ng-class="{full: vari.basket>0}">
<div ng-repeat="vari in pa.variacions">
<input type="number" ng-model="vari.basket" name="basket" min="0" max="20" step="1" ng-init="vari.basket=0">
</div>
</div>
So basically I want to add the full class when any of the vari items has a basket > 0.
So far is not working, what am I missing?

You can add a function in your controller that sets the class for your parent.
<div ng-repeat="pa in products" ng-class="{full: isFull(pa.variacions)}">
<div ng-repeat="vari in pa.variacions">
<input type="number" ng-model="vari.basket" name="basket" min="0" max="20" step="1" ng-init="vari.basket=0">
</div>
</div>
In your controller:
$scope.isFull = function(variacions) {
if (!Array.isArray(variacions)) {
return false;
}
return variacions.find(vari => vari.basket > 0);
}

<div ng-repeat="pa in products" ng-class="{true: 'myFullClass'}[$ctrl.isProductBasketFull(pa)]">
<div ng-repeat="vari in pa.variacions">
<input type="number" ng-model="vari.basket" name="basket" min="0" max="20" step="1" ng-init="vari.basket=0">
</div>
</div>
This isn't an ideal solution because of all the loops that would be generated but you could pass pa to a controller function that determines if a vari basket is full then return a boolean value.
In controller:
$scope.isProductBasketFull = function(pa){
for(var i=0,cnt=pa.length;i<cnt;i++)
if(pa[i].basket === maxVal) // whatever your max value is
return true;
return false;
};

Related

Replace text content of Current Target

I have 4 sliders on my website and would like to change the values of the slide and replace it with text.
$('.slider').on('input', (event) => {
if ($(event.currentTarget).val() === '0') {
$(event.currentTarget).text('test');
} else if (event.currentTarget.value === '1') {
console.log('display')
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="slidecontainer mx-4 text-center pb-4 w-50 mx-auto">
<input type="range" min="0" max="3" value="0" class="slider" id="range-bureautique">to be replaced
<div class="display linest" id="score-bureautique"></div>
</div>
</div>
With console.log() I can see that the value is getting equat to 0 or to 1 when i move the slider but the html content is not replaced with my 'test' text ...
Thanks!
This $(event.currentTarget).text('test') will update the text-content of the input-tag. But there is no such thing! Note that there is no end-tag to the input-tag. You should use some tag with id set ideally. Something like this:
<input ...><label id="my_label">to be replaced</label>
Then you use any of this jQuery thing to update the text:
$("#my_label").text('test');
$("#my_label").text($(event.currentTarget).val());
So with an update to the snippet:
$('.slider').on('input', (event) => {
$("#my_label").text($(event.currentTarget).val());
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="slidecontainer mx-4 text-center pb-4 w-50 mx-auto">
<input type="range" min="0" max="3" value="0" class="slider" id="range-bureautique">
<label id="my_label">to be replaced</label>
<div class="display linest" id="score-bureautique"></div>
</div>
</div>

How to validate number in inputs with javascript when pressing button?

Right now I have an Input Field (number) that shows a message when the numbers are over 120 or below 135.
//Message on Age
$("#age").keyup(function() {
if ($('#age').val() < 35 || $('#age').val() > 120) {
$('#errorMsg').show();
} else {
$('#errorMsg').hide();
}
<!-- AGE -->
<div class="card-2 p-20 hidden">
<div class="bg-white max-width p-20 mb-20">
<h2 style="margin-bottom: 50px;">What is your age?</h2>
<div class="options">
<input id="age" name="age" type="number" step="1" min="35" max="120" required="true" class="form-custom">
<span id="errorMsg" style="display:none;">Only policyholders between 35 and 120 years are elegible</span>
</div>
</div>
<div>
<button type="button" class="btn-previous">
Previous
</button>
<button type="button" class="btn-next">
Next
</button>
</div>
</div>
The issue is that user's still can press the button with the error message on the screen, I want to show the error message when they hit the button or invalidate the button if the age field isn't in range.
Thank you so much to anyone who can help on this!
You can use .prop function to disable your button if the condition matches and enable it if its all good.
Also, you can use $(this) to get the value of your input instead using if using #age id again in your .val().
In addtion you need to add + to your val() to make sure that strings value which are sting initially are converted into integers when checking the if condition.
Live Demo:
$("#age").on('input keyup', function() {
let btn = $('.btn-next')
let errorMsg = $('#errorMsg')
if (+$(this).val() < 35 || +$(this).val() > 120) {
errorMsg.show();
btn.prop('disabled', true)
} else {
errorMsg.hide();
btn.prop('disabled', false)
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="card-2 p-20 hidden">
<div class="bg-white max-width p-20 mb-20">
<h2 style="margin-bottom: 50px;">What is your age?</h2>
<div class="options">
<input id="age" name="age" type="number" step="1" min="35" max="120" required="true" class="form-custom">
<span id="errorMsg" style="display:none;">Only policyholders between 35 and 120 years are elegible</span>
</div>
</div>
<div>
<button type="button" class="btn-previous">
Previous
</button>
<button type="button" class="btn-next">
Next
</button>
</div>
</div>
You can change keyup to change jQuery method and implement sort of controller like this
// Controller
let cont = true;
// Validator
$("#age").on('change', function() {
if ($('#age').val() < 35 || $('#age').val() > 120) {
$('#errorMsg').show();
cont = true;
} else {
$('#errorMsg').hide();
cont = false;
}
});
$(".btn-next").on('click', function(event) {
if(cont) {
// Here do some warning you want
$('#errorMsg').show(function() {
alert($('#errorMsg').text());
});
// ALSO if this button gonna be SUBMIT
// button, you can set here prevent
// default mode like this:
//
//event.preventDefault();
} else {
// Validation ok, continue your logic
// ...
//
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!-- AGE -->
<div class="card-2 p-20 hidden">
<div class="bg-white max-width p-20 mb-20">
<h2 style="margin-bottom: 50px;">What is your age?</h2>
<div class="options">
<input id="age" name="age" type="number" step="1" min="35" max="120" required="true" class="form-custom">
<span id="errorMsg" style="display:none;">Only policyholders between 35 and 120 years are elegible</span>
</div>
</div>
<div>
<button type="button" class="btn-previous">Previous</button>
<button type="button" class="btn-next">Next</button>
</div>
</div>

how to have manage a prop in an html form in Vue.js / infinite loop prevention via computed property

I have a Vue.js signup form that has a bunch of similar fields. My understanding is that I should initialize the values as props and NOT as objects or arrays (because they will be pass-by-value).
I am using a computed property with getters / setters. I'd imagine that when I set my computed property, I need to emit to the parent component the value. Is this (in general) the correct way to do this? If not, what would be?
Also (and here's is the real question), if I emit from my setter and catch in the parent component, won't this just create an infinite loop as it gets passed back down as a prop? Or is there some mechanism within vue where if it doesn't change, it doesn't get re-emitted? IE, does assigning the same value as passed down by a props cause a watch-getter to fire?
Like the proposed component in first part and how it would be used in second:
Vue.component('signup-input',{
props:['placeholder','err','initialValue'],
template:`
<label>
<div class='signup-font'>Company Name Within Component</div>
<input #focus="err = null" v-model="tmpItem" :placeholder="placeholder" size="30" type="text" v-bind:class="{'no-margin error': err }" />
<label class="error copy-error" v-if="err">
{{err}}
</label>
</label>
`,
computed:{
tmpItem: {
get: function(){
return this.initialValue;
},
set: function(newValue){
console.log('here is newValue: ' + newValue);
// I emit here and wouldn't an infinite loop be caused?
}
}
},
})
var app7 = new Vue({
el: '#signup',
template: `
<div id="page-bg">
<signup-input :placeholder="companyName.placeholder" :err="companyName.err" :initialValue="companyName.value"></signup-input>
<label for="company_name">
<div class='signup-font'>Company Name</div>
<input #focus="companyName.err = null" placeholder="My Company" v-model="companyName.value" size="30" type="text" v-bind:class="{'no-margin error': companyName.err }" />
<label class="error copy-error" v-if="companyName.err">
{{companyName.err}}
</label>
</label>
I think you are looking for something like this. See docs for .sync
Vue.component('signup-input',{
props:['placeholder','err','initialValue'],
template:`
<label>
<div class='signup-font'>Company Name Within Component</div>
<input #focus="err = null" v-model="localValue" :placeholder="placeholder"
#input="$emit('update:initialValue', localValue)"
size="30" type="text" v-bind:class="{'no-margin error': err }" />
<label class="error copy-error" v-if="err">
{{err}}
</label>
</label>
`,
data() {
return {
localValue: this.initialValue
}
}
})
var app7 = new Vue({
el: '#signup',
template: `
<div id="page-bg">
<signup-input :placeholder="companyName.placeholder" :err="companyName.err" :initialValue="companyName.value"></signup-input>
<label for="company_name">
<div class='signup-font'>Company Name</div>
<input #focus="companyName.err = null" placeholder="My Company" v-model.sync="companyName.value" size="30" type="text" v-bind:class="{'no-margin error': companyName.err }" />
<label class="error copy-error" v-if="companyName.err">
{{companyName.err}}
</label>
</label>

bootstrap-slider link input number with slide change

I am using bootstrap-slider.js. My problem is that I can't link input number with a slide. I want to slide to change too if the input number is changed.
Slider
<div id="slider-year" class="search-block">
<h2 class="title">Production year</h2>
<div class="slider-year-amount">
<span class="pull-left">1900</span>
<span class="pull-right">2017</span>
</div>
<input type="text" class="year-slider" style="width:100%" data-slider-min="1900" data-slider-max="2017" data-slider-step="1" data-slider-value="[1900,2017]" />
<div class="row">
<div class="year-box">
<div class="col-lg-6">
<label>From</label>
<input type="number" min="1900" max="2019" class="form-control" placeholder="1900" id="minYear" value="1900" name="year_since">
</div>
<div class="col-lg-6">
<label>To</label>
<input type="number" min="1901" max="2020" class="form-control" placeholder="2017" id="maxYear" value="2017" name="year_to">
</div>
</div>
</div>
</div>
How I try to update slider:
jQuery("#minYear").change(function () {
jQuery("#slider-year").slider('setValue', jQuery(this).val());
});
Also here is documentation for this slider if anyone is curious, I couldn't find solution there: http://www.eyecon.ro/bootstrap-slider
JsFiddle: https://jsfiddle.net/y95vfds3/6/
Many years have passed... Anyway, here is my solution:
$('#year-slider').slider()
.on('slide', function(ev) {
$('#minYear').val(ev.value[0]);
$('#maxYear').val(ev.value[1]);
});
$('.form-control').on('input', function() {
let minVal = parseInt($('#minYear').val());
let maxVal = parseInt($('#maxYear').val());
$('#year-slider').slider('setValue', [minVal, maxVal])
});
https://jsfiddle.net/p98bcxuv/
Do you want like this?
$("#minYear").change(function() {
$("#slider-year").slider('setValue', jQuery(this).val());
});
val = $('.year-slider').slider();
$('.year-slider').on('slide', function(ev) {
$('#minYear').val(ev.value[0]);
$('#maxYear').val(ev.value[1]);
});
https://jsfiddle.net/gnanavelr/y95vfds3/7/
https://jsfiddle.net/gnanavelr/y95vfds3/8/

Javascript Document.getElementById returning null

I'm new to MVC and AJAX so this is probably a simple mistake I am making but using the code below, I am getting the following error trying to getElementById("txtCount").value:
<div class="row">
<div class="col-sm-4">
<div class="panel panel-primary">
<div class="panel-heading">
<h5 style="font-weight:bold;">Parameters</h5>
</div>
<div class="panel-body" id="parameters">
<form class="form-horizontal" id="frmParameters">
<div class="form-group">
<label for="txtCount" class="col-sm-4 col-form-label">Repeat</label>
<input type="number" min="1" max="100" step="1" id="txtCount" value="#Model.Count" class="input-sm col-sm-7" />
</div>
#if (Model.Grammar.SupportsMaxLength)
{
<div class="form-group">
<label for="txtMaxLength" class="col-sm-4 col-form-label">Max Length</label>
<input type="number" min="1" max="100" step="1" id="txtMaxLength" value="#Model.MaxLength" class="input-sm col-sm-7" />
</div>
}
<button name="btnGenerate" class="btn btn-primary pull-right" onclick="Generate();">Generate</button>
</form>
</div>
</div>
</div>
</div>
<script>
function Generate() {
var data = { count: document.getElementById("txtCount").value, maxLength: document.getElementById("txtMaxLength").value };
}
</script>
If I change:
var data = { count: document.getElementById("txtCount").value, maxLength: document.getElementById("txtMaxLength").value };
to:
var data = { count: document.getElementById("txtCount").value};
I don't get the error anymore.
Your code looks fine. I think you are getting the error when your code tries to execute this line
document.getElementById("txtMaxLength").value
Because in your view you are rendering this element when some if condition returns true. So it is possible that your view does not have this input element at all and you are trying to read that! (Check the view source of the page and search for input with txtMaxLength id.
The best solution is to check it exists before trying to read the value.
var data = {
id: "#Model.Id",
count: document.getElementById("txtCount").value,
maxLength: null // or whatever default value you want
};
if (document.getElementById("txtMaxLength")) {
data2.maxLength = document.getElementById("txtMaxLength").value;
}
Or if you are using jQuery library, it is easy
var data = {
id: "#Model.Id",
count: $("#txtCount").val(),
maxLength:$("#txtMaxLength").val()
};

Categories