jQuery select2 genemuFormBundle issue - forms

I am trying to implement ajax call using select2 as per this example:
https://github.com/genemu/GenemuFormBundle/blob/master/Resources/doc/jquery/select2/ajax.md
Here is my code:
var $configs = {{ configs|json_encode|raw }};
$field = $('#{{ id }}');
$configs = $.extend($configs, {
ajax: {
id: function (friend) { return friend.username; },
url: $field.data('url'),
data: function (term, page) {
return { q: term, page_limit: 10, page: page };
},
results: function (data, page) {
var more = (page * 10) < data.total;
return { results: data, more: more };
}
},
formatResult: function (friend) {
var markup = "<div class='friend-results-box'>";
if (friend.avatar !== undefined) {
markup += "<img width='60' height='75' src='" + friend.avatar + "'/>";
}
markup += "<h5>" + friend.username + "</h5>";
markup += "<div class'clearfix'></div>";
markup += "</div>";
return markup;
},
initSelection : function (element, callback) {
var elementText = $(element).attr('data-init-text'); // ?
callback({"term":elementText});
},
formatSelection: function (friend) { return friend.username; },
escapeMarkup: function (m) { return m; },
dropdownCssClass: "dropdown-friends"
});
$field.select2($configs);
Now my issues are:
Value is being filled in with ID when my intention is to have a
value taken from json defined there as friend.username
After page reload initial value is not being presented on the screen
(as value is being set to ID) and select2 does not pick it up
Any tips or help would be much appreciated!

Your initSelection function has this: callback({"term":elementText});
by default Select2 expects {id:"someid", text:"sometext"}
Best to start simple with no formatting of any kind, get that working then make it look like you want.

Related

SharePoint List Form Textfield to a dropdown

I've found a video from SharePointTech that explains how to change a textfield to a dropdown list on a List Form using data from open API. I'm trying to recreate it, but I'm hitting a roadblock with the new SharePoint Online. Instead of using "Country/Region", I created a new custom list with Company_Name. I took the person's code and made little changes that made a reference to "WorkCountry". When I save the changes (stop editing), the changes do not reflect and I get the same textfield. I had to use SharePoint Designer 2013 to create a new TestNewForm for new entry. Has anyone been able to reproduce this in SharePoint 2013 Designer? If so, would you be able an example?
I use jQuery's ajax method.
Updated code for your reference(you need to change the list name to your list name,InternalName is also):
<script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js">
</script>
<script>
var demo = window.demo || {};
demo.nodeTypes = {
commentNode: 8
};
demo.fetchCountries = function ($j) {
$.ajax({
url: _spPageContextInfo.siteAbsoluteUrl + "/_api/web/lists/getbytitle('Company_Name')/items",
type: "get",
headers: { "Accept": "application/json; odata=verbose" },
success: function (data) {
$j('table.ms-formtable td.ms-formbody').contents().filter(function () {
return (this.nodeType == demo.nodeTypes.commentNode);
}).each(function (idx, node) {
if (node.nodeValue.match(/FieldInternalName="Country_x002f_Region"/)) {
// Find existing text field (<input> tag)
var inputTag = $(this).parent().find('input');
// Create <select> tag out of retrieved countries
var optionMarkup = '<option value="">Choose one...</option>';
$j.each(data.d.results, function (idx, company) {
optionMarkup += '<option>' + company.Title + '</option>';
});
var selectTag = $j('<select>' + optionMarkup + '</select>');
// Initialize value of <select> tag from value of <input>
selectTag.val(inputTag.val());
// Wire up event handlers to keep <select> and <input> tags in sync
inputTag.on('change', function () {
selectTag.val(inputTag.val());
});
selectTag.on('change', function () {
inputTag.val(selectTag.val());
});
// Add <select> tag to form and hide <input> tag
inputTag.hide();
inputTag.after(selectTag);
}
});
},
error: function (data) {
console.log(data)
}
});
}
if (window.jQuery) {
jQuery(document).ready(function () {
(function ($j) {
demo.fetchCountries($j);
})(jQuery);
});
}
</script>
My source list:
Test result:
Updated:
<script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js">
</script>
<script>
var demo = window.demo || {};
demo.nodeTypes = {
commentNode: 8
};
demo.fetchCountries = function ($j) {
$.ajax({
url: 'https://restcountries.eu/rest/v1/all',
type: "get",
headers: { "Accept": "application/json; odata=verbose" },
success: function (data) {
$j('table.ms-formtable td.ms-formbody').contents().filter(function () {
return (this.nodeType == demo.nodeTypes.commentNode);
}).each(function (idx, node) {
if (node.nodeValue.match(/FieldInternalName="Country_x002f_Region"/)) {
// Find existing text field (<input> tag)
var inputTag = $(this).parent().find('input');
// Create <select> tag out of retrieved countries
var optionMarkup = '<option value="">Choose one...</option>';
$j.each(data, function (idx, company) {
optionMarkup += '<option>' + company.name + '</option>';
});
var selectTag = $j('<select>' + optionMarkup + '</select>');
// Initialize value of <select> tag from value of <input>
selectTag.val(inputTag.val());
// Wire up event handlers to keep <select> and <input> tags in sync
inputTag.on('change', function () {
selectTag.val(inputTag.val());
});
selectTag.on('change', function () {
inputTag.val(selectTag.val());
});
// Add <select> tag to form and hide <input> tag
inputTag.hide();
inputTag.after(selectTag);
}
});
},
error: function (data) {
console.log(data)
}
});
}
if (window.jQuery) {
jQuery(document).ready(function () {
(function ($j) {
demo.fetchCountries($j);
})(jQuery);
});
}
</script>
The difference in API will not have a great effect, the key is here '$ j.each (data, function (idx, company) {'. The structure of the return value of different APIs are different, you need to find useful data in return value.

Autopopulate field in suitecrm

I have this ajax call that populate the fields to a related field.
YAHOO.util.Event.onDOMReady(function() {
YAHOO.util.Event.addListener(
"parent_module_another_module_ida",
"change",
ajaxReq
);
function ajaxReq() {
var propertyId = $("#parent_module_another_module_ida").val();
if (propertyId != "") {
$.ajax({
url: "/?entryPoint=ajaxEntryPoint&module=Parent_Module&id=" + propertyId,
success: function(result) {
var res = JSON.parse(result);
$("#price").val(res['price']);
}
});
}
}
});
The fields gets auto populated but the format becomes something like 1000.000000 ive tried to modify the precision in its vardefs to 0 but its still the same i want to format the number if possible to something like this 1,000.
You will need to use toFixed function of javascript to get the required results.
Following is the modified code:
YAHOO.util.Event.onDOMReady(function() {
YAHOO.util.Event.addListener(
"parent_module_another_module_ida",
"change",
ajaxReq
);
function ajaxReq() {
var propertyId = $("#parent_module_another_module_ida").val();
if (propertyId != "") {
$.ajax({
url: "/?entryPoint=ajaxEntryPoint&module=Parent_Module&id=" + propertyId,
success: function(result) {
var res = JSON.parse(result);
price_val = res['price'].toFixed(0);
$("#price").val(price_val);
}
});
}
}
});

Add new data from restful api to angularjs scope

I'm trying to create a list with endless scroll in angularjs. For this I need to fetch new data from an api and then append it to the existing results of a scope in angularjs. I have tried several methods, but none of them worked so far.
Currently this is my controller:
userControllers.controller('userListCtrl', ['$scope', 'User',
function($scope, User) {
$scope.users = User.query();
$scope.$watch('users');
$scope.orderProp = 'name';
window.addEventListener('scroll', function(event) {
if (document.body.offsetHeight < window.scrollY +
document.documentElement.clientHeight + 300) {
var promise = user.query();
$scope.users = $scope.users.concat(promise);
}
}, false);
}
]);
And this is my service:
userServices.factory('User', ['$resource',
function($resource) {
return $resource('api/users', {}, {
query: {
method: 'GET',
isArray: true
}
});
}
]);
How do I append new results to the scope instead of replacing the old ones?
I think you may need to use $scope.apply()
When the promise returns, because it isnt
Part of the angular execution loop.
Try something like:
User.query().then(function(){
$scope.apply(function(result){
// concat new users
});
});
The following code did the trick:
$scope.fetch = function() {
// Use User.query().$promise.then(...) to parse the results
User.query().$promise.then(function(result) {
for(var i in result) {
// There is more data in the result than just the users, so check types.
if(result[i] instanceof User) {
// Never concat and set the results, just append them.
$scope.users.push(result[i]);
}
}
});
};
window.addEventListener('scroll', function(event) {
if (document.body.offsetHeight < window.scrollY +
document.documentElement.clientHeight + 300) {
$scope.fetch();
}
}, false);

Load Jquery Accordion after button click using Jquery

I am using JQuery UI Accordion, it works fine with the static content. However when i am loading the H3 and Div tags of the accordion from the ajax rest service call. The data is coming up properly but accordion is not loading up
onSuccess: function (data) {
var results = data.d.query.PrimaryQueryResult.RelevantResults.Table.Rows.results;
var html = "";
for (var i = 0; i < results.length; i++) {
html += "<div><h3><a href=\"#\">";
html += results[i].Cells.results[3].Value;
html += "</a></h3><p>"
html += results[i].Cells.results[6].Value;
html += "</p></div>";
}
$("#results_accordion").accordion();
My Accordion Div is empty initially whihc i want to fill up with the data from the above service call on button click.
$("#results_accordion").accordion();
Any help ?
$("#results_accordion").html(html).accordion();
you should first add the html content to your page before you execute the accordion function
This is my actual click event which is called..
function onclic(queryTerms) {
Results = {
element: '',
url: '',
init: function (element) {
Results.element = element;
Results.url = someurl;
},
load: function () {
$.support.cors = true;
$.ajax(
{
url: Results.url,
method: "GET",
headers: {
"accept": "application/json;odata=verbose",
},
success: Results.onSuccess,
error: Results.onError
}
);
},
onSuccess: function (data) {
var results = data.d.results;
var html = "";
for (var i = 0; i < results.length; i++) {
html += "<div><h3><a href=\"#\">";
html += results[i].Cells.results[3].Value;
html += "</a></h3><p>"
html += results[i].Cells.results[6].Value;
html += "</p></div>";
}
Results.element.html(html);
$("#results_accordion").accordion();
},
onError: function (err) {
alert(JSON.stringify(err));
}
}
Results.init($('#results_accordion'));
Results.load();
$("#results_accordion").accordion();
}

How to reuse jquery-ui-autocomplete cached results when appending search term?

I have the following JS method to bind the jQuery UI autocomplete widget to a search text box. Everything works fine, including caching, except that I make unnecessary server calls when appending my search term because I don't reuse the just-retrieved results.
For example, searching for "ab" fetches some results from the server. Typing "c" after "ab" in the search box fetches "abc" results from the server, instead of reusing the cached "ab" results and omitting ones that don't match "abc".
I went down the path of manually looking up the "ab" search results, filtering them using a regex to select the "abc" subset, but this totally seems like I'm reinventing the wheel. What is the proper, canonical way to tell the widget to use the "ab" results, but filter them for the "abc" term and redisplay the shortened dropdown?
function bindSearchForm() {
"use strict";
var cache = new Object();
$('#search_text_field').autocomplete({
minLength: 2,
source: function (request, response) {
var term = request.term;
if (term in cache) {
response(cache[term]);
return;
}
$.ajax({type: 'POST',
dataType: 'json',
url: '/get_search_data',
data: {q: term},
success: function (data) {
cache[term] = data;
response(data);
}
});
});
}
Here's my "brute-force, reinventing the wheel" method, which is, for now, looking like the right solution.
function bindSearchForm() {
"use strict";
var cache = new Object();
var terms = new Array();
function cacheNewTerm(newTerm, results) {
// maintain a 10-term cache
if (terms.push(newTerm) > 10) {
delete cache[terms.shift()];
}
cache[newTerm] = results;
};
$('#search_text_field').autocomplete({
minLength: 2,
source: function (request, response) {
var term = request.term.toLowerCase();
if (term in cache) {
response(cache[term]);
return;
} else if (terms.length) {
var lastTerm = terms[terms.length - 1];
if (term.substring(0, lastTerm.length) === lastTerm) {
var results = new Array();
for (var i = 0; i < cache[lastTerm].length; i++) {
if (cache[lastTerm][i].label.toLowerCase().indexOf(term) !== -1) {
results.push(cache[lastTerm][i]);
}
}
response(results);
return;
}
}
$.ajax({type: 'POST',
dataType: 'json',
url: '/get_search_data',
data: {q: term},
success: function (data) {
cacheNewTerm(term, data);
response(data);
return;
}
});
});
}
If anyone wants a version that supports multiple entries in the text box then please see below:
$(function () {
function split(val) {
return val.split(/,\s*/);
}
function extractLast(term) {
return split(term).pop();
}
var cache = new Object();
var terms = new Array();
function cacheNewTerm(newTerm, results) {
// keep cache of 10 terms
if (terms.push(newTerm) > 10) {
delete cache[terms.shift()];
}
cache[newTerm] = results;
}
$("#searchTextField")
.on("keydown",
function (event) {
if (event.keyCode === $.ui.keyCode.TAB &&
$(this).autocomplete("instance").menu.active) {
event.preventDefault();
}
})
.autocomplete({
minLength: 2,
source: function (request, response) {
var term = extractLast(request.term.toLowerCase());
if (term in cache) {
response(cache[term]);
return;
} else if (terms.length) {
var lastTerm = terms[terms.length - 1];
console.log('LAst Term: ' + lastTerm);
if (term.substring(0, lastTerm.length) === lastTerm) {
var results = new Array();
for (var i = 0; i < cache[lastTerm].length; i++) {
console.log('Total cache[lastTerm[.length] = ' +
cache[lastTerm].length +
'....' +
i +
'-' +
lastTerm[i]);
console.log('Label-' + cache[lastTerm][i]);
var cachedItem = cache[lastTerm][i];
if (cachedItem != null) {
if (cachedItem.toLowerCase().indexOf(term) !== -1) {
results.push(cache[lastTerm][i]);
}
}
}
response(results);
return;
}
}
$.ajax({
url: '#Url.Action("GetSearchData", "Home")',
dataType: "json",
contentType: 'application/json, charset=utf-8',
data: {
term: extractLast(request.term)
},
success: function (data) {
cacheNewTerm(term, data);
response($.map(data,
function (item) {
return {
label: item
};
}));
},
error: function (xhr, status, error) {
alert(error);
}
});
},
search: function () {
var term = extractLast(this.value);
if (term.length < 2) {
return false;
}
},
focus: function () {
return false;
},
select: function (event, ui) {
var terms = split(this.value);
terms.pop();
terms.push(ui.item.value);
terms.push("");
this.value = terms.join(", ");
return false;
}
});