I render a select multiple in Ractive with a computed list of all options possible, which works great. But I could not find a proper way of preselecting values.
So far I have something like:
data = [{
type: "Person",
Name: "John",
worksFor: [
"1",
"2"
]},{
type: "department",
id: "1",
Name: "Sales"
},{
type: "department",
id: "2",
Name: "Marketing"
},{
type: "department",
id: "3",
Name: "Accounting"
}]
new Ractive({
el: '#list',
template: DataTpl,
data: {myData: data},
computed: {
DepartmentList () {
//some code
return list_of_all_Departments;
},
PersonsList () {
//some Code
return list_of_persons
});
So in my Template I tried
{{#PersonsList}}
<select multiple>
{{#DepartmentList}}
<option value="{{id}}"
{{#if _.includes(PersonsList.worksFor, id)}} selected{{/if}}>{{Name}}
</option>
{{/DepartmentList}}
</select>
{{/PersonsList}}
But this just gave me a failed to compute. Does anyone know how to get those preselects?
This is one of the things where Ractive deviates from standards. You need to put a value attribute on <select>. The selected <option>'s value becomes <select>'s value. The kind of data you'll get from <select> depends if it's multiple or not. If it's a single-select, you get a single value. If it's multiple-select, you'll get an array.
Setting a pre-selected value is simply the other way around. Assign a value from your data to <select>'s value and, assuming those values exist on the <option>s, they'll be selected. No template mangling required.
Ractive.DEBUG = false;
var data = [{
type: "Person",
Name: "John",
worksFor: [
"1",
"2"
]
}, {
type: "department",
id: "1",
Name: "Sales"
}, {
type: "department",
id: "2",
Name: "Marketing"
}, {
type: "department",
id: "3",
Name: "Accounting"
}];
new Ractive({
el: '#list',
template: '#template',
data: {
selectedDepartments: [],
myData: data
},
computed: {
DepartmentList() {
return this.get('myData').filter(v => v.type === 'department');
},
PersonsList() {
return this.get('myData').filter(v => v.type === 'Person');
}
}
});
<script src="https://unpkg.com/ractive#0.8.11/ractive.min.js"></script>
<div id="list"></div>
<script type="template/ractive" id="template">
{{#PersonsList}}
{{ Name }}
<select multiple value="{{ worksFor }}">
{{#DepartmentList}}
<option value="{{id}}">{{Name}}</option>
{{/DepartmentList}}
</select>
{{/PersonsList}}
</script>
you must give the select a value and set the value to whatever is the default value
Related
so i was trying to make a button that when clicked it copy a value from a variable
like
<button onclick="copyToClipboard()">COPY</button>
and then on that function it takes the element to copy from a variable like
var copyids = {
"ids": [
{
"name": "id1",
"id": 192389021
},
{
"name": "id2",
"id": 123879032
},
{
"name": "id3",
"id": 149018292
},
]
};
so like copyids.ids[0].id and it copy that value
i hope its understandable
Maybe this helps
function copyToClipboard() {
let temp = document.createElement('textarea');
temp.value = copyids.ids[0].id;
document.body.appendChild(temp);
temp.select();
document.execCommand('copy');
document.body.removeChild(temp);
}
To copy, you will need to select before what you want to copy. Maybe you should put the data of the variable somewhere and copy it.
https://www.w3schools.com/howto/howto_js_copy_clipboard.asp
I made you a solution with the ability to select the desired data cell from the array. I've added a select tag for you, listing the name of each cell.
And at the choice of a specific option with you copy id in accordance with the specified name.
function copyToClipboard() {
var copyids = {
ids: [
{
name: "id1",
id: 192389021,
},
{
name: "id2",
id: 123879032,
},
{
name: "id3",
id: 149018292,
},
],
};
let selectIndex = document.querySelector("select").selectedIndex;
let storage = document.createElement("input");
storage.value = copyids.ids[selectIndex].id;
console.log(storage.value);
document.body.appendChild(storage);
storage.select();
document.execCommand("copy");
document.body.removeChild(storage);
}
<button onclick="copyToClipboard()">COPY</button>
<select>
<option value="id1">id1</option>
<option value="id2">id2</option>
<option value="id3">id3</option>
</select>
The execCommand method has been deprecated, and it might not be supported by newer releases.
However, there is a Clipboard API that you can use in it's place.
To let the user select what to copy from your list:
<button onclick="copyToClipboard()">COPY</button>
<select>
<option value="id1">id1</option>
<option value="id2">id2</option>
<option value="id3">id3</option>
</select>
Then your function can work like this:
function copyToClipboard() {
var copyids = {
ids: [
{
name: "id1",
id: 192389021,
},
{
name: "id2",
id: 123879032,
},
{
name: "id3",
id: 149018292,
},
],
};
let selectedIndex = document.querySelector("select").selectedIndex;
navigator.clipboard.writeText(copyids[selectedIndex].name);
i'm trying to get the selected option of a user task.
myresult
what my expected result is like this expected
Here is my Html code
<div class="form-group has-float-label">
<input v-model="form.name" type="text" name="name" placeholder="Name" class="form-control" :class="{ 'is-invalid': form.errors.has('name') }">
<has-error :form="form" field="name"></has-error>
</div>
<div class="form-group">
<select name="tasks" v-model="form.tasks" id="tasks" class="form-control" :class="{ 'is-invalid': form.errors.has('tasks') }">
<option disabled value="">Please select one</option>
<option v-for="t in alltask" :key="t"
v-bind:value="t" >{{t.name}}
</option>
</select>
<br />
{{form.tasks}}
</div>
Below is my JS code
<script>
export default {
data() {
return {
editmode: false,
users : {},
alltask : {},
form : new Form({
id: '',
name: '',
tasks: {},
})
}
},
methods: {
loadUsers(){
axios.get("/api/v1/users").then(({ data }) => (
this.alltask = data.alltask,
this.users = data.users
));
},
editModal(user){
this.editmode = true;
this.form.reset();
$('#users').modal('show');
this.form.fill(user);
}
},
created() {
this.loadUsers();
}
}
</script>
this is my json response
{
"users": [
{
"id": 1,
"name": "zxc",
"username": "zxc",
"tasks": [
{
"id": 1,
"name": "cooking"
}
]
},
{
"id": 2,
"name": "foo",
"username": "foo",
"tasks": [
{
"id": 2,
"name": "cleaning"
}
]
}
],
"alltask": [
{
"id": 1,
"name": "cooking"
},
{
"id": 2,
"name": "cleaning"
}
]
}
the value of v-model is the same with option value but i don't get it to get pre selected upon clicking update button, but if i change the option the v-model code that i put below the v-model itself is getting changed following the option list and i can update it to the db
The Problem is that you bind the whole object as value. Even though the object you receive from your call and the object you used to bind the value property to have the same "content" (props & values) they are not the same. So it will not be preselected.
What you actually should do is only bind the id of the task and if you want to display the result find the object that has the id from your alltask list
https://jsfiddle.net/eywraw8t/382079/
<select v-model="form.task">
<option>Please Select</option>
<option :value="t.id" v-for="(t, i) in alltask" :key="i">{{ t.name }}</option>
</select>
<p>
{{ selectedTask }}
</p>
As you only select one task I was wondering why you have "form.tasks" - for my example I changed it to singular.
The computed prop selectedTask could look like this
computed: {
selectedTask() {
return this.alltask.find(task => {
return task.id === this.form.task
})
}
}
I'm very new to angularjs and need some advice about the angular way to implement something very simple. In my $scope I need to set some field defaults, and these defaults are needed multiple times in my controller.
I want to be able to refactor these defaults out to a common place, to thin out the controller and allow for code reuse, but not sure if this should be a factory, directive or service.
Heres an example of the defaults:
$scope.skills = [{
description: '',
years: "1",
level: "0",
years_values: [
{ id: "1", description: "1" },
{ id: "2", description: "2" },
{ id: "3", description: "3+" }],
level_values: [
{ id: "0", description: "Starter"},
{ id: "1", description: "Intermediate"},
{ id: "2", description: "Advanced"} ]
}]
Here's an example of where I'd like to call the "new function":
skillSuccess = (resp)->
Loader.hide();
$rootScope.current_user = resp;
#TODO replace this repetition
$scope.skills = [{
description: '',
.... etc
My questions are:
Should I use a factory/directive/service, (or something else) for
this refactoring?
How do I ensure that the function gets called
initially so that the default values are available for the fields
when the page loads?
Should I use a factory/directive/service, (or something else) for this
refactoring?
I'd suggest you to create a constant because looks like you have defaults data which has initially has some value and that will going to be change by the user from the front-end. So you could place that in angular constant, then that constant will be accessed by the factory/service. And Factory/service will do the needful manipulation from its function. To make available constant in your service/factory you need to inject constant name in your service.
By looking at your current requirement you shouldn't be take consideration of directive component.
Constant
app.constant('defaults', [{
description: '',
years: "1",
level: "0",
years_values: [
{ id: "1", description: "1" },
{ id: "2", description: "2" },
{ id: "3", description: "3+" }],
level_values: [
{ id: "0", description: "Starter"},
{ id: "1", description: "Intermediate"},
{ id: "2", description: "Advanced"} ]
}]);
Service
app.service('dataService', function(defaults){
var dataService = this;
dataService.defaults = defaults;
dataService.defaults = angular.copy(defaults) //will return same copy every-time
dataService.getDefaults = function(){
return dataService.defaults;
}
//other method will lie here
})
How do I ensure that the function gets called initially so that the default values are available for the fields when the page loads?
You could simply get that defaults by consuming getDefaults method of your service, then stored that retrieved defaults and use those for manipulation.
If you want the defaults copy to instantiated every-time then use angular.copy(defaults) which will give you the copy of defaults.
Controller
app.controller('myCtrl', function($scope, dataService){
$scope.defaults = dataService.getDefaults(); //this will have defaults
//...other stuff here...
});
Should I use a factory/directive/service, (or something else) for this refactoring?
A controller should be used to set the scope, but the default values should be stored as a constant and returned by a factory. A factory pattern is preferred here because it is a singleton.
angular.module('myApp')
.factory('skillsFactory', function (defaultSkills) {
var service = {};
service.getDefaults = function () {
return defaultSkills;
};
return service;
})
.constant('defaultSkills', [{
description: '',
years: "1",
level: "0",
years_values: [{
id: "1",
description: "1"
}, {
id: "2",
description: "2"
}, {
id: "3",
description: "3+"
}],
level_values: [{
id: "0",
description: "Starter"
}, {
id: "1",
description: "Intermediate"
}, {
id: "2",
description: "Advanced"
}]
}]);
How do I ensure that the function gets called initially so that the default values are available for the fields when the page loads?
In your controller, call $scope.skills = skillsFactory.getDefaults();
angular.module('myApp')
.controller('skillsCtrl', function ($scope, skillsFactory) {
$scope.skills = skillsFactory.getDefaults();
});
I'm giving following data input to select2
data = [{
"id": "all",
"text": "All",
"children": [{
"id": "item1",
"text": "item1"
}, {
"id": "item2",
"text": "item2"
}]
}];
and I'm initialising select2 as:
$(parent).select2({"data":data});
Now to select the value "item1", I did
$(parent).select2("val",["item1"]);
However instead of value "item1" value "all" is getting selected. How to select value item1?
To set the selected value using select2 you should use:
$(parent).val("item1").trigger("change");
From the release notes:
You should directly call .val on the underlying element instead. If you needed the second parameter (triggerChange), you should also
call .trigger("change") on the element.
$("select").val("1"); // instead of $("select").select2("val", "1");
JSFiddle where item1 is selected.
JS:
var data = [{
id: 'all',
text: 'All',
children: [{
id: 'item1',
text: 'item1'
}, {
id: 'item2',
text: 'item2'
}]
}];
$('.js-example-data-array').select2({data:data});
$('.js-example-data-array').select2('val',['item1']);
HTML:
<select class="js-example-data-array">
</select>
I tried to make this demo to show you that it works. The demo, uses the select tag as a selector for an empty and existing select element. Indeed, I don't know what are you meaning by parent:
<select>
</select>
<script>
data = [{
"id": "all",
"text": "All",
"children": [{
"id": "item1",
"text": "item1"
}, {
"id": "item2",
"text": "item2"
}]
}];
$('select').select2({
"data": data
});
$('select').select2("val", ["item2"]);
</script>
I'm not sure if you mean that the value "All" gets selected at start or if you want to select "item1" by code and it doesn't work. I find it strange that "All" gets selected as value since it should be treated as a category, even by adding
$(".select2-text").select2("val",["item1"]);
it won't select "All" for me. If i add
$(".select2-text").select2("val",["item2"]);
It will select "item2" for me (which means the method to select the item works, though it's not the best way, as stated in Lelio Faieta's Answer)
if i add
$(".select2-text").select2("val",["all"]);
it won't select "All" for me, it will just show me a blank select. So I think there must be an issue with your code because in a clean page there seems to be no way to select "All"
Can you show us the whole code, including the html of your page (at least the part relevant to the select). I have tried this (see plunker here: http://plnkr.co/edit/m6pFUt?p=preview )
<script>
$(document).ready(function() {
data = [{
"id": "all",
"text": "All",
"children": [{
"id": "item1",
"text": "item1"
}, {
"id": "item2",
"text": "item2"
}]
}];
$(".select2-text").select2({
"data": data
});
});
</script>
<select class="select2-text"></select>
And it starts with item1 selected, while "All" is treated as a category. So maybe it's just because something is wrong in your code/HTML.
What version of Select2 are you using? i'm using 2-4.0.0
bit of background: when a user clicks an element, it loads a form retrieved by an ajax call. I save a copy of the json in the controller, and when they change a value, it is to update the local json.
Let's say the json is something like this:
{
name: "questions!",
id: "0",
questions: [{
id: "1",
text: "ninjas or pirates?",
type: "radio",
answers: [{
id: "1",
text: "ninjas"
} , {
id: "2",
text: "pirates"
}],
}, {
id: "3",
text: "why?",
type: "text"
answers: []
}]
}
the element returned is a jquery-ized version of the input that was selected.
While I could iterate through each field and check, I can't help but feel like there is a better way to do it and reference it more directly. How would this be done?