I can't compare my date using MomentJs and Vue - vue.js

I would like to find if my duration is > 0. I use MomentJs and Vue to get my duration using this code :
moment3: function (date) {
var now = moment();
var day = moment(date);
var duration = day.diff(now);
return parseInt(duration);
},
I get the duration correctly (2987546325 in example). But still this code not working.
<a v-if="event.time | moment3 > 0"> Do somethingHere </a>
Thank you for help.

I assume that you're trying to use moment3 as a Vue filter function.
There are two problems here:
You can't use a filter function in a v-if expression. They're only available inside a {{ ... }} or a v-bind expression.
You can't put anything after a filter function, other than the function's arguments or another filter function. So the > 0 isn't allowed even if you were in a {{ ... }} or v-bind.
See https://v2.vuejs.org/v2/guide/filters.html
The | character will just be interpreted as JavaScript's bitwise OR operator in this case.
You'd probably be better off just using a method instead. So define moment3 inside your component's methods and then call it using v-if="moment3(event.time) > 0".

Related

vue does not recover from me specifying a non existing location for v-model

When I have a textarea like
<textarea v-model="foo.abc.text"></textarea>
and either foo or foo.abc does not exist yet then
vue removes either parts of the DOM or is giving me a blank page.
It does never recover.
That alone is annoying, regardless of if I am using a debug version of vue or not.
If I try to use an approach that I have been advised to use earlier like
<textarea v-model="foo?.abc?.text"></textarea>
then I am still out of luck, I presume that I get a "rvalue" using those question marks and what I need rather is a variable location.
How do I, with as little trickery as possible, allow v-model to exist later on even if it doesnt exist now (late binding)?
Just shape your data accordingly and initialize it with empty values:
data(){
return {
foo: {
abc: {
text: ''
}
}
}
}
You can later populate it e.g. with the result of api call, but it's still better to initialize data properly
I would suggest going the :value + #input way. It allow more control over the input model, and does not require hiding it.
<textarea :value="!!foo && foo.abc.text" #input="(val) => !!foo && (foo.abc.text = val)" />
You can even hook in a validator:
<textarea
:value="!!foo && foo.abc.text"
#input="(val) => !!foo && (foo.abc.text = val)"
:rules="v => !v && 'The object has not been initialised'"
/>
I found a solution I can live with and then I got a comment in the same direction:
Conditionally showing the textarea.
v-if seems to do it but it falls under the "trickery" category, I think (angularjs would be more relaxed).
<textarea v-if="foo!=null" v-model="foo.abc"></textarea>
The symptom to hiding components if something is not all correct is not the best part of vue.js. Better show them and color them red.

How to increment a variable in a Golang template? [duplicate]

How can you calculate something inside a html template of go?
For example:
{{ $length := len . }}
<p>The last index of this map is: {{ $length -1 }} </p>
Were the . is a map.
The code {{ $length -1 }} is not working, is there a way to achieve this?
You can't. Templates are not a scripting language. By design philosophy, complex logic should be outside of templates.
Either pass the calculated result as a parameter (preferred / easiest), or register custom functions which you can call during template execution, pass values to them and which may perform calculations and return any values (e.g. return param - 1).
For examples of registering and using custom functions, see:
Golang templates (and passing funcs to template)
How do I access object field by variable in template?
Iterate Go map get index.
The other answers are correct, you can't do it in the template themselves. However, here's a working example of how to use Funcs:
package main
import (
"fmt"
"html/template"
"os"
)
type MyMap map[string]string
func LastMapIndex(args ...interface{}) string {
if m, ok := args[0].(MyMap); ok && len(args) == 1 {
return fmt.Sprintf("%d", len(m) - 1)
}
return ""
}
func main() {
myMap := MyMap{}
myMap["foo"] = "bar"
t := template.New("template test")
t = t.Funcs(template.FuncMap{"LastMapIndex": LastMapIndex})
t = template.Must(t.Parse("Last map index: {{.|LastMapIndex}}\n"))
t.Execute(os.Stdout, myMap)
}
Playground: https://play.golang.org/p/YNchaHc5Spz
You can use a FuncMap like this. Once you define a function within a funcmap, you can use it in the HTML. In your case you could define a MapLength function or something similar that calculates the length of a given map and returns it for you. You can then call it in the template a bit like this:
<p>The last index of this map is: {{ .MapLength . }} </p>

Vee validate: isBetween custom rule with parameters not working

validate, and Im trying to create multiple rules for my textfield for example: required, minlength, maxLength and chain them together, and based on whic h parameter is passed to preform validation
So I tried using example from the docs:
http://vee-validate.logaretm.com/v2/guide/custom-rules.html#args-and-rule-configuration
const isBetween = (value, { min, max } = {}) => {
return Number(min) <= value && Number(max) >= value;
};
// The first param is called 'min', and the second is called 'max'.
const paramNames = ['min', 'max'];
Validator.extend('between', isBetween, {
paramNames // pass it in the extend options.
});
And my Vue model looks like this:
<ValidationProvider
v-if="item && item.type === 'TEXT_AREA'"
:rules="`isBetween:true, 10`"
v-slot="{ errors, valid, validate }"
>
<b-form-textarea
size="sm"
:id="`attribute`"
:value="attributeValue"
#input="addAttributeValue($event, uid, validate)"
/>
<span>{{ displayError(errors) }}</span>
</ValidationProvider>
Here I try to pass in IsBeterrn params like: required, length and based on that to preform validation but I always get min & max value as null, and arguments is array instead of object
Also my second question is how would I use required from vee-validate in my custom rule
You have two ways of specifying parameters, with strings or with objects. I suggest you use the object method like this:
<ValidationProvider
:rules="{between:[0, 10]}"
>
You had a couple mistakes - the rule is called between because that's what you called it when you did this:
Validator.extend('between', isBetween, {
paramNames // pass it in the extend options.
});
Also, you can't use a boolean and a number as the parameter as you did here:
:rules="`isBetween:true, 10`"
The way I specified it, with :rules="{between:[0, 10]}" also lets you make the min and max variable if you wanted, i.e. if you had a component data item called minValue you could use that in the rule like this :rules="{between:[minValue, 10]}" and your rules would react to changes to minValue.

Vue: Filter returns an array, how to get the first element

Lets say I have a custom filter cf.js that needs to return multiple values in an array like this:
export default (value) => {
var a = 5
var b = 3
return [a, b]
}
In my vue file, how can I display only the first element? I thought something like below would work but they do not
{{ myvar | cf[0] }} or {{ (myvar | cf)[0] }}
You're limited by the filter syntax in the Vue template, so what you tried won't work.
A filter doesn't make sense in the example you've given since it doesn't make use of the argument.
But anyway, to answer your question, two options come to mind:
1. Define another filter to get the first element
{{ myvar | cf | first }}
export default function first(value) {
return value[0]
}
2. Call the filter function manually
This will allow you to do what you want with the filter result since you're just calling it as if it were any other function.
{{ $options.filters.cf(myvar)[0] }}

A complex condition inside v-if

I want to create a complex condition to pass to the v-if directive.
I have tried the following.
<div v-if="(order.order_products[key].statuses[0].id) != 3 || order.status != 3" >
Can I add a complex condition in Vue's v-if? This is not working.
I also tried with && but that wasn't working, either. I haven't found anything in the documentation about this.
Firstly, to answer your question.
Can I add a complex condition in Vue's v-if?
You can pass an arbitrary JavaScript expression to the v-if directive in Vue, including a complex boolean expression which contains operators || or &&.
You can test this on your own. For example, try having the following template.
<div v-if="true && false">I am not visible!</div>
Of course, you might try out something less trivial, too:
<div v-if="1 == 2 || (1 + 2 == 3 && 4 == 4)">I am visible!</div>
Your expression looks good, but based on the provided information it's impossible to deduce what exactly is wrong.
Your problem is something else: maybe the data is not in the format you thought it would be, or maybe your logic has a flaw in it.
Yes, you can set complex condition. I suggest you to use Vue computed fields, so you will have better highlight (through Vue Devtools) of variables which use in v-if expression. I suppose that order is data field, so you can set computed fields like this:
computed: {
orderStatusId: function () {
// Write some checks is variable defined/undefined
return this.order.order_products[key].statuses[0].id
},
orderStatus: function () {
return this.order.status
}
}
and v-if expression should look like this:
<div v-if="orderStatusId !== 3 || orderStatus !== 3" >
In this approach you can review values of variables in your v-if expression.
Yes, you can use any JavaScript expresion inside v-if quotes.
But I recommend you to create a function or computed function and to call it inside your if statement, for better readability.
ex:
computed: {
shouldDisplay: function () {
return this.order.order_products[key].statuses[0].id) !== 3 || this.order.status !== 3;
}
...
}
<div v-if="shouldDisplay"> ... </div>
v-if="(segmento != 4) && (segmento != 2) && (segmento != 8)"
Works like a breeze for me!