Vue: Filter returns an array, how to get the first element - vue.js

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] }}

Related

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.

I can't compare my date using MomentJs and Vue

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".

How to alphabetically sort a list of options in Vue.js / Buefy form?

Currently I display a list of hotels for each city in a Vue.js / Buefy form using:
<option
:value="h['#attributes'].Name"
v-for="h in cities[form.cities[i].index].Hotels.Hotel"
:key="cities[form.cities[i].index].Hotels.Hotel.Name"
v-if="isArray(form.cities[i].index)"
v-text="h['#attributes'].Name"></option>
What should I add to sort them alphabetically? I'm at loss, as I don't know Vue / Buefy so well and I'm modifying a code somebody else wrote.
Thanks!
It is important to understand what your code is doing so that you know where you need to make changes.
Your loop v-for is iterating over your array cities[form.cities[i].index].Hotels.Hotel (the naming seems odd to me).
Within this array, there is a key #attributes which holds an object with a key Name, which is probably what you want to use for sorting.
Normally I would go with computed properties for these things but since you have the array based on a parameter (form.cities[i].index) I am not sure that would work so easily. So instead you can use a method to get a sorted version of your array. In your Vue instance, add the following to the "methods" property:
methods: {
sortedHotels: function(hotels) {
tmp = this.hotels.slice(0);
tmp.sort(function(a,b) {
return (a['#attributes'].Name > b['#attributes'].Name) ? 1 : ((b['#attributes'].Name> a['#attributes'].Name) ? -1 : 0);
});
return tmp;
},
},
Then, instead of looping through the normal array, you loop through the result of the function call of that array:
<option
:value="h['#attributes'].Name"
v-for="h in sortedHotels(cities[form.cities[i].index].Hotels.Hotel)"
:key="cities[form.cities[i].index].Hotels.Hotel.Name"
v-if="isArray(form.cities[i].index)"
v-text="h['#attributes'].Name"></option>

how to push values in array and pass these values to Select tag

I want to push values in array and pass these values as options of select tag. I did following,
used plugin
import DropDown, {
Select,
Option,
OptionList,
} from 'react-native-selectme';
assigned state as
this.state = {company:[]};
pushing in this array as
for(let i in data.companyRecord)
company.push(data.companyRecord[i].companyname);
and assigning to select tag as
<Select
width={250}
ref="SELECT1"
optionListRef={this._getOptionList.bind(this)}
defaultValue="Select a Company ..."
onSelect={this._company.bind(this)} asyncOptions={this.state.company}>
</Select>
But it is not working. It is showing that
undefined is not an object('evaluating children.length').
Please help me solving this issue.
You can't edit the state like that.
const tempNames = [];
for(let i in data.companyRecord)
tempNames.push(data.companyRecord[i].companyname);
this.setState({ company: tempNames });
Now your state will have the correct values.
But there might still be some problem, because your error might suggest that this.state.company is undefined, however you correctly assigned this.state.company to an empty array before.
This could be due to this.state is undefined. Are you defining your selector in a own created function? And not in your class own render method? In that case you need to bind this to your method.
renderSelector() {
return (<Select
width={250}
ref="SELECT1"
optionListRef={this._getOptionList.bind(this)}
defaultValue="Select a Company ..."
onSelect={this._company.bind(this)} asyncOptions={this.state.company}>
</Select>);
}
In your constructor you need to bind "this" to that method. Like this:
this.renderSelector = this.renderSelector.bind(this);