I have spent a couple of hours trying to figure out how to properly reset a form with token field on alpaca.js.
Not sure if this is a bug, or I am doing something wrong. I placed two reset buttons, a generic one and a second one that calls a function to reset the form.
<script type="text/javascript">
var value = {};
$("#myform").alpaca({
"schema": {
"title": "token field",
"type": "object",
"properties": {
"text_field": {"type": "text" },
"token_field": { "type": "token"},
}
},
"options": {
"fields": {
"text_field": {
"label": 'this is a text field',
"type": "text"
},
"token_field": {
"label": 'this is a token field',
"type": "token",
"tokenfield": {
},
},
},
"form": {
"buttons": {
"load": {
label:"load saved values",
"click": function() {
$('form#' + this.attributes.id)[0].reset();
this.setValue(value);
},
},
"reset": {},
"fancy_reset": {
"label": "reset with function",
"click": function() {
console.log(this.attributes.id);
$('form#' + this.attributes.id)[0].reset();
},
},
"save": {
label:"save",
"click":function(){
value = this.getValue();
console.log(this.getValue());
console.log(value);
},
},
},
},
},
});
</script>
Any insights on whats wrong here?
I've been working with Alpaca for year but I haven't use that type of and after some research I haven't found any solution in the Alpaca lib to reset that type of field, so I tried to use jquery and bootstrap tokenizer methods.
and I've came to this solution :
Create an eventlistener to the reset form event
$('form').on('reset', function(e) {
var control = $("#myform").alpaca("get");
var field = control.childrenByPropertyId['token_field'];
field.refresh();
});
In your load function after this.setValue(value) add this code:
if (typeof value.token_field != undefined) {
// getting Alpaca parent control (this holds everything)
var control = $("#myform").alpaca("get");
// get the token field
var field = control.childrenByPropertyId['token_field'];
// setting the saved token to the field using bs-tokenizer method setTokens
$(field.control).tokenfield('setTokens', value.token_field);
}
Here's a fiddle for that.
Tell me if you still have any issue.
Related
I have an array of towns - each town has a label and a value. Then there is an HTML input which should display the town label selected and on submit send the relevant value. A JQuery script with a filter that chooses the town based on the beginning characters of the label and not the characters in the rest of the label body. I need the script to, filter as designed, but when a town is selected, the HTML id #dtags must display the label and the #dtag must submit the value via a hidden input.
I have two scripts, each one does ONE of the above successfully, but I am battling to get one script to combine both "features".
I am looking for some assistance to create a single JQuery script to achieve the above. My JQuery skills are limited and the code below is what I have managed to find through searching and adapting - credit to the originators.
Please see code below:-
<div class="ui-widget">
<input id="dtags" class="form-control col-md-8" placeholder="Choose Delivery Town" required>
<input id="dtag" type="hidden" name="deltown">
</div>
<script>
(function() {
var towns = [
{ "label": "AANDRUS, Bloemfontein", "value": 1 },
{ "label": "AANHOU WEN, Stellenbosch", "value": 2 },
{ "label": "ABBOTSDALE, Western Cape", "value": 3 },
{ "label": "ABBOTSFORD, East London", "value": 4 },
{ "label": "ABBOTSFORD, Johannesburg", "value": 5 },
{ "label": "ABBOTSPOORT, Limpopo", "value": 6 },
{ "label": "ABERDEEN, Eastern Cape", "value": 7 },
{ "label": "ACKERVILLE, Witbank", "value": 8 },
{ "label": "ACORNHOEK, Mphumalanga", "value": 9 },
{ "label": "ACTIVIA PARK, Germiston", "value": 10 }
];
$("#dtags").autocomplete({
source: towns
});
// Overrides the default autocomplete filter function to search only from the beginning of the string
$.ui.autocomplete.filter = function (array, term) {
var matcher = new RegExp("^" + $.ui.autocomplete.escapeRegex(term), "i");
return $.grep(array, function (value) {
return matcher.test(value.label || value.value || value);
});
};
})();
//Uses event.preventDefault(); to halt the default and works as below
// $("#dtags").autocomplete({
//minLength: 1,
//source: towns,
//select: function(event, ui) {
//event.preventDefault();
//$("#dtags").val(ui.item.label);
//$("#dtag").val(ui.item.value);
//}
//});
//});
//});
//});
</script>
In case this could help anyone in the future, this is the script that I managed to get working successfully as per the question - slight change as to using an external data source:-
<script>
(function() {
var towns = [<?php require_once("towns.txt")?>];
$("#dtags").autocomplete({
source: towns,
select: function( event, ui ) {
$("#dtags").val(ui.item.label);
$("#dtag").val(ui.item.value);
return false;
}
});
// Overrides the default autocomplete filter function to search only from the beginning of the string
$.ui.autocomplete.filter = function (array, term) {
var matcher = new RegExp("^" + $.ui.autocomplete.escapeRegex(term), "i");
return $.grep(array, function (value) {
return matcher.test(value.label || value.value || value);
});
};
})();
</script>
I have an Alpaca JS form comprised of an array of items which each consist of a textbox and a checkbox. For some reason, when I change the order using the dynamic controls, it successfully renumbers the textbox but doesn't change the number of the checkbox. This also results in a duplicate name assigned if the same top button to dynamically add new fields is pressed. The end result is incorrect data being passed when the form is submitted. How can I fix this to properly renumber the checkboxes?
Here's a sample of the Alpaca configuration:
$("#form1").alpaca({
"schema": {
"title": "Testing checkbox array IDs",
"description": "Testbox checkbox array test.",
"type": "object",
"properties": {
"form-fields": {
"title": "Fields",
"description": "These are the fields.",
"type": "array",
"items": {
"type": "object",
"properties": {
"field-name": {
"type": "string",
"title": "Field Name",
"description": "Enter the name for this field.",
"required": true
},
"field-box": {
"type": "boolean",
"title": "Field Box",
"description": "Check this box.",
"default": false
}
}
}
}
}
}
});
I couldn't find a way to correct the behavior itself but I was able to work around it by adding a postRender event to the Alpaca definition as follows:
"postRender": function(control) {
control.childrenByPropertyId["form-fields"].on("move", function() { $('input[type=checkbox]').each(function(index) { $(this).attr("name", $(this).closest("div:has(*[name])").first().attr("name")) }); });
control.childrenByPropertyId["form-fields"].on("add", function() { $('input[type=checkbox]').each(function(index) { $(this).attr("name", $(this).closest("div:has(*[name])").first().attr("name")) }); });
control.childrenByPropertyId["form-fields"].on("remove", function() { $('input[type=checkbox]').each(function(index) { $(this).attr("name", $(this).closest("div:has(*[name])").first().attr("name")) }); });
}
This is a bit of a hack but it works because the parent object does get assigned the correct name value and the form will post with those values if the name is just copied down into the input elements.
I have a JavaScript object as shown below.
{
"28903218": {
"type": "group",
"prompt": "Cool, thanks! Now tell us about your child's day:",
"description": ""
},
"37742463": {
"type": "choice",
"prompt": "How does {{answer_28903220}} react in an unwelcome situation?",
"description": "(Such as not wanting to be in the car seat, when you're not in the room at bedtime, etc.)"
},
"30035493": {
"type": "choice",
"prompt": "Friday:",
"description": ""
},
}
I have a problem to read it. How can I get the 28903218 property's value?
surveyData.getQuestions().subscribe(
result => {
//here I need to get the "28903218" object's value
},
err => { },
() => { }
);
Assuming that you know 28903218:
var value = result["28903218"];
If you don't know it then you could loop through the properties until you find the desired one:
for (var prop in result) {
var value = result[prop];
}
I'm using angucomplete-alt (https://github.com/ghiden/angucomplete-alt) in an AngularJS project, however I can't seem to make it work.
I'm trying to build a really simple autocomplete form, like this:
<angucomplete-alt pause="400" selected-object="obj" remote-api-handler="search" title-field="id" minlength="1" />
And my function is defined in the controller as such:
$scope.search= function (userInputString, timeoutPromise) {
return $timeout(function () {
return [{ "id": "1" }, { "id": "2" }, { "id": "3" }]
}, 1000);
However, everytime I try to search, I get "No results", even though the console logs no errors and the function is being called fine. What am I doing wrong?
Ok, I've found a solution. Even though it's not specified at all in the docs, the directive expects a response like:
{"data": [Array of objects]}
Therefore, it works if I do it like:
$scope.search= function (userInputString, timeoutPromise) {
return $timeout(function () {
return {"data": [{ "id": "1" }, { "id": "2" }, { "id": "3" }]};
}, 1000);
Hope it will help others.
I am trying to configure a custom context menu for jsTree. I want files to have two options [Rename, Delete] and I want folders to have one option [Create]
The below code seems correct as described here: Configuring jstree right-click contextmenu for different node types
However this does not seem to work, there are two problems.
Both context menus display the options [Rename, Delete]
Choosing either option
causes the error: Uncaught TypeError: undefined is not a function
What am I doing wrong?
Edit: here is a fiddle
$( document ).ready(function() {
function customMenu(node) {
// The default set of all items
var items = {
createItem: { // The "create" menu item
label: "Create",
action: function () {
this.create(node);
}
},
renameItem: { // The "rename" menu item
label: "Rename",
action: function () {
this.rename(node);
}
},
deleteItem: { // The "delete" menu item
label: "Delete",
action: function () {
this.remove(node);
}
}
};
if ($(node).hasClass("folder") || $(node).hasClass("jstree-closed") || $(node).hasClass("jstree-open")) {
delete items.deleteItem;
delete items.renameItem;
}
else{
delete items.createItem;
}
return items;
}
$('#tree').jstree({
'core': {
'data': [
{ "id": "ajson1", "parent": "#", "text": "Folder 1" },
{ "id": "ajson2", "parent": "ajson1", "text": "File 1" },
{ "id": "ajson3", "parent": "ajson1", "text": "File 2" }
]
},
"plugins": [ "contextmenu" ],
"contextmenu": {items: customMenu}
});
});
Okay so the answer is that jstree does not implicitly distinguish between files and folders. If you want to make the distinction you need to add an identifier and custom logic.
To accomplish this I added the following to each of my data objects.
"data" : { "file" : true }
The custom logic then became
if (node.data.file) {
delete items.createItem;
}
else{
delete items.deleteItem;
delete items.renameItem;
}
Furthermore, the manner in which I was implementing custom actions was wrong. I figured this out by looking at the source of jstree (jstree/src/jstree.contextmenu.js). To enable create and delete you must set 'check_callback': true. Then you can for example implement the create action as follows.
createItem: { // The "create" menu item
label: "Create",
action: function (data) {
var inst = $.jstree.reference(data.reference),
obj = inst.get_node(data.reference);
inst.create_node(obj, {}, "last", function (new_node) {
new_node.data = {file: true};
setTimeout(function () { inst.edit(new_node); },0);
});
}
},
Full working jsfiddle here.