Setting initial value for computed property with vuejs - javascript

I'm trying out vuejs by following along with the laracasts series of webcasts on this. In https://laracasts.com/series/learning-vue-step-by-step/episodes/6, Jeffery Way has put the code in the http://jsfiddle.net/d4f27e5p/ .
The initial setting is shown in the screenshot, before any plan is selected. I would like to set a default value in the button of "please select " (instead of "Downgrade") The button code is:
<span v-else>
<button #click="setActivePlan">
{{ isUpgrade ? 'Upgrade' : 'Downgrade' }}
</button>
How can I do this?

How about adding a computed property for the button text that includes the additional logic? Something like this:
buttonText: function() {
if(!this.active.name)
return "Please Select";
return this.isUpgrade ? 'Upgrade' : 'Downgrade';
}
Then the button would use this:
<span v-else>
<button #click="setActivePlan">
{{ buttonText }}
</button>
</span>
Here's an updated jsfiddle.

Related

dynamic form in django using choiceField

I'm building my first web app with django and am having a hard time figuring out how to use dynamic form in order to have different output for different selected choice.
for example, for my measure choice qualitative, I want the form be the same(no extra fields) but if the quantitative value is selected, I want my template to show two more fields(value_min and value_max)
the first option when qualitative value is selected
the second option when quantitative value is selected
thank you for your help...
You can't use the django tags for conditions, because it only renders from the backend, so this is a frontend issue. In my implementations I normally use javascript with the following idea:
Start with the values min and max not displayed (style.display = "None")
AddEventListener (onChange type) to the selector (in your case, Mesure)
Check if the condition is met with javascript and change the style.display to block, for example
Forms are rendered on the template before the page load. So, django variables cannot e manipulated by the user.
While rendering your form, django allows you to set classes to the form fields. use them to hide the extra fields.
example value_min = forms.CharField(widget=forms.TextInput(attrs={'class':'hide'}))
you may add a form check while clean
class MYform(forms.Form):
#....
def clean_min_value(self):
#check here for choice field value
#return value or blank accordingly
similarly you can add validators to the form to ensure this value is only set if choice is set to quantitative
value_min = forms.CharField(widget=forms.TextInput(attrs={'class':'hide'}), validators=[check_choice])
def check_choice(Value):
# validate Value
thanks #videap and #Rhea for your help... so I figured out how to resolve my problem using the guidance of videap and the post Show and hide dynamically fields in Django form
So the solution was:
for the form :
class NewCriterioForm(forms.ModelForm):
parent = TreeNodeChoiceField(queryset=Criteria.objects.all())
def __init__(self,*args,**kwargs):
super().__init__(*args,**kwargs)
self.criteria_CHOICES = [('FunCriteria','FunCriteria'),('nonFunCriteria','nonFunCriteria')]
self.mesure_CHOICES = (('Quantitative','Quantitative'),('Qualitative','Qualitative'))
self.fields['parent'].label=''
self.fields['parent'].required=False
self.fields['type']= forms.CharField(widget=forms.Select(choices=self.criteria_CHOICES))
self.fields['mesure']= forms.ChoiceField(choices=self.mesure_CHOICES)
class Meta:
model = Criteria
fields = ('name', 'parent', 'type','slug','description','mesure','value_min','value_max')
}
for the view :
......
criterion = NewCriterioForm()
return render(request, 'addCriteria.html', {'criterion': criterion})
and finaly, in the template , I put this code:
<script>
function Hide() {
if(document.getElementById('id_mesure').options[document.getElementById('id_mesure').selectedIndex].value == "Qualitative") {
document.getElementById('id_value_min').style.display = 'none';
document.getElementById('id_value_max').style.display = 'none';
} else {
document.getElementById('id_value_min').style.display = '';
document.getElementById('id_value_max').style.display = '';
}
}
window.onload = function() {
document.getElementById('id_mesure').onchange = Hide;
};
</script>
<div>
{{ criterion.name.label_tag }}{{ criterion.name }}
</div>
<tr></tr>
<div>
{{ criterion.parent.label_tag }}{{ criterion.parent }}
</div>
<div>
{{ criterion.type.label_tag }}{{ criterion.type }}
</div>
<div>
{{ criterion.slug.label_tag }}{{ criterion.slug }}
</div>
<div>
{{ criterion.description.label_tag }}{{ criterion.description }}
</div>
<div>
{{ criterion.mesure.label_tag }}{{ criterion.mesure }}
</div>
<div id="id_value_min">
{{ criterion.value_min.label_tag }}{{ criterion.value_min }}
</div>
<div id="id_value_max">
{{ criterion.value_max.label_tag }}{{ criterion.value_max }}
</div>

Conditionally render a badge for active/inactive User

I am trying to render conditionally a badge, based on the logged condition of a user. If the props coming from the server is true, then the badge is green, else grey.
I have tried various solutions, from basic if/else in the JSX, to classNames but the badge isn't being render.
My Code:
{user.loggedIn ? (
<div
className={classNames('badge badge-pill', {
'badge-success': user.loggedIn,
'badge-danger': !user.loggedIn
})}
/>
I don't see anything wrong with the code. I mean the item should have rendered, with multiple solutions. Any ideas, what I am doing wrong.
<span
className={
user.loggedIn ? 'badge badge-pill badge-success' : 'badge badge-pill badge-muted'
}
/>
I have tried this as well.
I can see the element in the React-Dev-Tools, being render correctly, witht the right prop, but I cannot see it render in the screen.
Your contents will only get rendered if user is loggedIn. Also the div tag must be closed inside the condition { isLoggedIn }
you should try something like this:
{user.loggedIn ? (
<div className={'badge badge-pill badge-success'}>ENTER YOUR CONTENT HERE</div>) : (
<div className={'badge badge-pill badge-danger'}>ENTER YOUR CONTENT HERE</div>
)}
but since the div is self-closing and has no contents, it doesn't display it, so add some content too
The badge for logged out user will never be displayed as you put a rendering condition around all the div with user.loggedInd ? (yourComponent...)
If user.loggedIn is boolean, then you can just write
<div
className={
classNames('badge badge-pill', {
'badge-success': user.loggedIn,
'badge-danger': user.loggedIn
})
}
/>
I think it's better to avoid conditional in jsx directly. You can do something like this:
let attachClass = ['badge', 'badge-pill']
if(user.loggedIn){
attachClass = [...attachClass, 'badge-success'].join(' ');
}else{
attachClass = [...attachClass, 'badge-danger'].join(' ');
}
Than you can just return one div with className attach class:
<div className={attachClass}></div>
The issue look into the user.loggedIn is not defined or return false
const loggedIn = true;
<span className={loggedIn ? 'badge-success' : 'badge-muted'}>
Css Change </span>
Codepen

Conditional V-HTML rendering

Just wondering if there is something I'm missing here:
<span v-html="(shouldParseHTMLBool ? HTMLContent : '')">
{{ contentWithoutParsedHTML }}
</span>
doens't appear to work.
I would like to have this span interpreting HTML only if shouldParseHTMLBool is set to true.
Is it something possible, or should I use a v-if? In this trivial example it's not a big deal, but with my components I'll have to duplicate ~30 lines for each condition.
It's better to make if condition away from template as much as possible.
You should create a computed object instead.
[template]
<span v-html="computedContent"></span>
[script]
...
computed: {
computedContent: function () {
return this.shouldParseHTMLBool ? this.HTMLContent : ''
}
},
...
The v-html directive replaces the innerHTML of the element. In your case, the {{ contentWithoutParsedHTML }} will be replaced with the value of (shouldParseHTMLBool ? HTMLContent : '')
You can do something like
<template>
<span v-html="conditionalParse"></span>
</template>
<script>
methods: {
conditionalParse: function () {
return this.shouldParseHTMLBool ? this.HTMLContent : ''
}
</script>
try this
<span v-if="shouldParseHTMLBool" v-html="HTMLContentForIfCondition" >All</span>
<span v-else v-html="HTMLContentForElseCondition" ></span>
You can use two spans, One for v-if is true and other for v-else

Proper way to express switch statement with Vue data bindings

I have a simple use case for a range input that changes a button's text whenever the range's value changes. I'm using Vue.js to bind data from an object that is simply storing the range value, and spitting it back out to the button (and the counter, for easier debugging).
In the following fiddle, when the range value is greater than 0, the text reads "Buy", or else it reads "Sell".
Fiddle: http://jsfiddle.net/svwa79pe/1/
What I want to do is show three button states depending on whether the range value is positive, negative, or zero. I can use Vue handlebar / mustache syntax to create a ternary expression, but I can't figure out how cover the third state. What I need is closer to a switch statement than ternary, but I can't seem to find an analog to that within Vue's documentation.
Does Vue contain a tool for this kind of logic that I don't know about?
Should I just handle this with a custom method that fires on the range change?
Am I just using the Vue template incorrectly? Is there a better way to do this with attributes or something?
HTML
<div id="app">
<span>
<button disabled="true">{{ item.delta }}</button>
</span>
<input type="range" v-model="item.delta" value="0" v-bind:max="item.stock" v-bind:min="0 - item.loot">
<span class="exchange">
<button>
{{ (item.delta > 0) ? "Buy" : "Sell" }}
</button>
</span>
</div>
JS
var stats = {
item : {
price : 10,
stock : 20,
loot : 5,
delta : 0
}
}
var app = new Vue({
el: '#app',
data: stats
});
Typically you want to remove complex logic from the template. In this case you want a value based on some other data so this is an ideal use case for a computed property.
computed:{
btnText(){
if (this.item.delta > 0) return "Buy"
if (this.item.delta < 0) return "Sell"
return "Nothing"
}
}
Here I'm just using simple if statements, but if you wanted to use a switch you certainly could. Used in your template like this:
<button>
{{ btnText }}
</button>
Here is a working example.
var stats = {
item : {
price : 10,
stock : 20,
loot : 5,
delta : 0
}
}
var app = new Vue({
el: '#app',
data: stats,
computed:{
btnText(){
if (this.item.delta > 0) return "Buy"
if (this.item.delta < 0) return "Sell"
return "Nothing"
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.2/vue.min.js"></script>
<div id="app">
<span>
<button disabled="true">{{ item.delta }}</button>
</span>
<input type="range" v-model="item.delta" value="0" v-bind:max="item.stock" v-bind:min="0 - item.loot">
<span class="exchange">
<button>
{{ btnText }}
</button>
</span>
</div>

Double click to edit element in Meteor app

I am making a school project in Meteor.js for a hospital - the prototype of the app is up on http://lrh.meteor.com . In the view doctors section in the table, I want to double click on the record and be able to edit the Name and the email id, but along with this I also want to update in record in MongoDB collection. Any ideas about how I can implement this feature?
I think this can help you.
Lets create this helper.
Template.example.helpers({
'editValue' : function(){
return Session.get("TargetValue" + this._id);
}
})
And this 2 events.
Template.example.events({
'dbclick #spanIdOnDom' : function(e,t){
return Session.set("TargetValue" + t.data._id,true)//hide the span and we set the input
},
'click #buttonToSaveNewValue': function(e, t) {
//here you can take the emailId and the name based on this._id like this Collection.find({_id:this._id}).fetch(); and do the updates you want to do
var newValueFromInput = document.getElementById('newValueFromInput').value;
var idCurrentDocument = this._id;
var Bebida = Collection.findOne(t.data._id);
Collection.update({_id: idCurrentDocument}, {$set:{fieldToUpdate: newValueFromInput}});
return Session.set("TargetValue" + t.data._id,false); //we hide the input and we put the span again
}
})
HTML
<template name="example">
{{#each collectionFind}}
{{#if editValue}}
<input type="text" id="newValueFromInput" value="{{currentValue}} " />
<button class="btn btn-sm btn-primary" id="buttonToSaveNewValue" type="submit">Save new Value</button>
{{else}}
<td>
<p>
<span class="content col-md-10" id="spanIdOnDom" ><h4>Descripcion Bebida:</h4><br>{{currentValue}} </span>
</p>
</td>
{{/if}}
{{/each}}
</template>
Of course you need to set your Allow/deny Permission and publish/subscribe methods to make it work more efficient.
How it works?
in resume you have an <span> tag with the current value, when you dobleClick on the <span> tag , we set the Session to true, the <span> tag go away and a new <input> appears with a new button then we take the value from the <input> and she update ($set) into the collection, and its done.
NOTE: this is a mini-repo from Simple Crud app in Meteor from Raj Anand, but the code on the blogs is on coffee and i don't use coffee Script.

Categories

Resources