I am new to backbone and am using backbone in my rails application . This is what I am doing in my application
I am using Backbone Paginator for pagination support in my application as well using Gmaps for rendering locations on gmaps , for each time I am displaying 5 records from the server with pagination and displaying corresponding 5 location in map view , so now I need to show the remaining locations on map when I click on paginated links (prev page , next page) , I think I need to write some click events , but I am not sure where to write and how to write this events , Can any one please help me . please review the code below I have written evnets but those are not working
Thanks in advance
var Listings = Backbone.PageableCollection.extend({
model: Bdemo.Models.Listing,
mode: "server" ,
url: '/listings' ,
events: {
"click #paginationSelect" : "fetchSelectedData"
},
fetchSelectedData: function(){
console.log("CAMEEEEEEEEEEEEEEEEEEEEEEEEEEE")
},
// Initial pagination states
state: {
pageSize: 3,
/* sortKey: "updated",*/
order: 1
},
queryParams: {
totalPages: null,
totalRecords: null,
sortKey: "sort"
},
parseState: function (resp, queryParams, state, options) {
return {totalRecords: resp.total_pages};
},
parseRecords: function (resp, options) {
return resp.listings;
}
});
#ratnakar:
All you need is events function. Set an id for each of your paginated links. Then include the events function. I hope that you're developing SPA(single page application). With that note assume the following settings.
In the homeview.js("templates" folder) page include the paginated links enclosed by the footer tag.
<footer>
<button id="prevPage">previous</button>
<button id="nextPage">next</button>
</footer>
then the go to the corresponding homeview.js view file("views" folder)
backboneApp.Views.homeview = Backbone.View.extend({
//Default "events" function for handling delegate events.
events:{
//catching click events
"click #prevPage" : "goPrevious" //on click of DOM which has id as prevPage, calling a function goPrevious.
"click #nextPage" : "goNext" //same as above call goPrevious function.
},
//Defining the user created function goPrevious and goNext.
goPrevious: function(){
//Make your server call here.... for the previous 5 records.
},
goNext: function(){
// server call here for the next 5 records.
}
});
Thus the basic idea of using delegate events for paginated links is defined above.
From your question I understand that you are using backgrid-paginator in server mode.
Binding to the click event won't work, because you need to make sure that the models have been fetched from the server before you can access their data.
You can bind to your collections' request event and act on the xhr.done()
In your view:
initialize: function() {
this.listenTo(this.record_collection, "request", this.onCollectionRequested);
},
onCollectionRequested: function(collection, xhr, options) {
_this = this;
xhr.done(function(){
_this.showRecordLocationsOnMap(collection);
})
},
showRecordLocationsOnMap: function(records) {
/* Update your map here */
}
Hi finally solved this by calling my own function(callGmap) from Backbone.PageableCollection , here is my new code
var Listings = Backbone.PageableCollection.extend({
model: Bdemo.Models.Listing,
mode: "server" ,
url: '/listings' ,
events: {
"click #paginationSelect" : "fetchSelectedData"
},
fetchSelectedData: function(){
console.log("CAMEEEEEEEEEEEEEEEEEEEEEEEEEEE")
},
// Initial pagination states
state: {
pageSize: 3,
/* sortKey: "updated",*/
order: 1
},
queryParams: {
totalPages: null,
totalRecords: null,
sortKey: "sort"
},
parseState: function (resp, queryParams, state, options) {
return {totalRecords: resp.total_pages};
},
parseRecords: function (resp, options) {
callGmap(resp.hash);
return resp.listings;
}
});
Related
I've been working with a great audio recorder which is recorder.js-master.
But I can't make the upload work with MVC Controller.
Here's my javascript function.
function AudioUpload(title, description) {
Recorder.upload({
method: "POST",
url: '#Url.Action("Upload", "Audio")',
audioParam: "Recording",
params: {
"Title": title,
"Description": description
},
success: function (responseText) {
alert(responseText.Success);
},
error: function () {
alert("error");
},
progress: NULL
});
}
Here's my AudioController
public JsonResult Upload(VoicePassage passage)
{
//upload Audio
return Json(new { Success = true });
}
I have a breakpoint in Upload just to know that it's going to my Controller but it doesn't.
Please help.
Here's the reference I follow. http://marc.codewisp.com/2013/05/07/in-browser-audio-recording-recorder-js-asp-net-mvc/?replytocom=12#respond
Regards,
Christian
I'm the author of the original post you linked to.
A few things to try out:
Add a breakpoint to the JavaScript function: if it doesn't hit, something's wrong with your JavaScript.
Check your browser's network activity: In Chrome, under Developer Tools, go to the Network tab and attempt the upload. See if it is hitting the right URL.
Make sure you're using '#Url.Action...' inside a Razor view. It won't work in external JavaScript files.
If you need #Url.Action, you can probably use it in your Razor view, assign it to a temporary global variable and use it in your external JavaScript file.
In your View, add the following before the reference to your external JS:
<script type="text/javascript">
var audioAction = '#Url.Action("Upload", "Audio")';
</script>
In your JavaScript file, change '#Url.Action("Upload", "Audio")' to audioAction, as in:
function AudioUpload(title, description) {
Recorder.upload({
method: "POST",
url: audioAction,
audioParam: "Recording",
params: {
"Title": title,
"Description": description
},
success: function (responseText) {
alert(responseText.Success);
},
error: function () {
alert("error");
},
progress: NULL
});
}
I have two views in database. Bonuses and employees. One(employee)-to-many(bonuses).
I have kendo ui grid (kendo web), which displays ajax results from controller called Bonuses
And an autocompliting element - Employee Combobox binded with Employee filed of a grid.
Grid's datasource:
// bind json result from /Bonuses/GetPagedJsonBonuses
var bonusesDataSource = new kendo.data.DataSource({
transport: {
read: "#Url.Action("GetPagedJsonBonuses", "Bonuses")",
update: {
url: "#Url.Action("Edit", "Bonuses")",
type: "PUT"
},
create: {
url: "#Url.Action("Create", "Bonuses")",
type: "POST"
},
parameterMap: function(options, operation) {
if (operation === "update" || operation === "create") {
// updates the BonusDTO.EmployeeId with selected value
if (newValueEmployeeId !== undefined)
options.EmployeeId = newValueEmployeeId;
}
return options;
}
},
schema: {
data: "Data", // PagedResponse.Data
total: "TotalCount", // PagedResponse.TotalCount
model: {
id: "BonusId", // Data
fields: {
EmployeeId: { type: "number" },
EmployeeLastName: {
type: "string",
editable: true,
//validation: { required: {message: "Employee's last name is required"}}
},
Amount: {
type: "number",
editable: true,
nullable: false,
validation: {
required: { message: "Amount is required to be set" }
}
}
} // fields
} // model
}// schema
});
Grid element looks like this:
// creates bonuses grid control
$("#bonusesGrid").kendoGrid({
dataSource: bonusesDataSource,
toolbar: ["create"],
editable: "inline",
columns: [
"BonusId",
"EmployeeId",
{
field: "EmployeeLastName",
editor: employeeAutocompletingEditor,
template: "#=EmployeeLastName#"
},
"Amount",
{
command: ["edit"],
title: " "
}
],
save: function(e) {
if (newValueEmployeeId !== undefined && newValueEmployeeLastName !== undefined) {
e.model.EmployeeId = newValueEmployeeId; // it's a hack to bind model and autocomplete control
e.model.EmployeeLastName = newValueEmployeeLastName;
}
},
edit: function(e) {
setCurrentValueEmployeeIdAndLastName(e.model.EmployeeId, e.model.EmployeeLastName);
},
cancel: function(e) {
setCurrentValueEmployeeIdAndLastName(e.model.EmployeeId, e.model.EmployeeLastName);
}
});
Autocompleting combobox has it's own datasource using ajax:
// datasource for autocomlete combobox to lookup employees names from
var employeesDataSource = new kendo.data.DataSource({
transport: {
read: "#Url.Action("GetJsonEmployeesByLastName", "Bonuses")",
},
parameterMap: function(options, operation) {
if (operation === "update" || operation === "create") {
setNewValueEmployeeIdAndLastName(options.Id, options.LastName);
}
return options;
},
});
Autocompliting combobox look's like this:
function employeeAutocompletingEditor(container, options) {
$('<input required data-text-field="LastName" data-value-field="EmployeeId" data-bind="value:' + options.field + '"/>')
.appendTo(container)
.kendoComboBox({
// sets the local variables to update values of current row.
change: function() {
setNewValueEmployeeIdAndLastName(this.value(), this.text());
},
dataBinding: function (e) {
console.log("dataBinding: ", e, this.dataItem());
},
dataBound: function (e) {
console.log("dataBound: ", e, this.dataItem());
},
dataSource: employeesDataSource
});
}
I use Editor binding to pass values(EmployeeId) and Text (EmployeeLastName) from grid to combobox.
I also use a hack like temporal variables (newValueEmployeeId, currentValueEmployeeId) to
send selected Employee in combobox and pass it to grid for correct save. A found it's a most common practice to pass a value back to grid.
My problems is:
If I press Edit button on my grid first time The combobox displays current employee's name from grid row:
If I press Cancel button and again press Edit button, combobox doesn't display current value of grid (employee's name)
IF I type some name, change some other values, and Udate(save) value, next time combobox again displays employees name, but only once before Cancel was pressed.
I'm very new in Kendo UI and this problem drives me crazy...
I think that combobox losts it's binding or doesn't update smth. I tried to set values while onBound and onBinding events, but this doesn't help. Please help me with an advice and example.
PS all evenets and functions is my try to debug and find solution.
only one fix helped me:
var employeeList = new List<Employee>()
employeeList.add(new Emplpyee()) // add fake employee record.
return Json(employeeList)
I don't know why, but grid control start make cyclying empty ajax requests if I return empty list of employees or null. This doesn't work:
return Json(new List<Employee>());
return Json(null);
I think it's a problem in kendo combobox itself ,because it's not ready to receive and handle empty list or null as json result.
Also I heared something, that JQuery doesn't support empty or null results anymore...maybe that's the reason
I want to have a dropdown with a set of values but also allow the user to "select" a new value not listed there.
I see that select2 supports this if you are using it in tags mode, but is there a way to do it without using tags?
The excellent answer provided by #fmpwizard works for Select2 3.5.2 and below, but it will not work in 4.0.0.
Since very early on (but perhaps not as early as this question), Select2 has supported "tagging": where users can add in their own value if you allow them to. This can be enabled through the tags option, and you can play around with an example in the documentation.
$("select").select2({
tags: true
});
By default, this will create an option that has the same text as the search term that they have entered. You can modify the object that is used if you are looking to mark it in a special way, or create the object remotely once it is selected.
$("select").select2({
tags: true,
createTag: function (params) {
return {
id: params.term,
text: params.term,
newOption: true
}
}
});
In addition to serving as an easy to spot flag on the object passed in through the select2:select event, the extra property also allows you to render the option slightly differently in the result. So if you wanted to visually signal the fact that it is a new option by putting "(new)" next to it, you could do something like this.
$("select").select2({
tags: true,
createTag: function (params) {
return {
id: params.term,
text: params.term,
newOption: true
}
},
templateResult: function (data) {
var $result = $("<span></span>");
$result.text(data.text);
if (data.newOption) {
$result.append(" <em>(new)</em>");
}
return $result;
}
});
For version 4+ check this answer below by Kevin Brown
In Select2 3.5.2 and below, you can use something like:
$(selector).select2({
minimumInputLength:1,
"ajax": {
data:function (term, page) {
return { term:term, page:page };
},
dataType:"json",
quietMillis:100,
results: function (data, page) {
return {results: data.results};
},
"url": url
},
id: function(object) {
return object.text;
},
//Allow manually entered text in drop down.
createSearchChoice:function(term, data) {
if ( $(data).filter( function() {
return this.text.localeCompare(term)===0;
}).length===0) {
return {id:term, text:term};
}
},
});
(taken from an answer on the select2 mailing list, but cannot find the link now)
Just for the sake of keep the code alive, I'm posting #rrauenza Fiddle's code from his comment.
HTML
<input type='hidden' id='tags' style='width:300px'/>
jQuery
$("#tags").select2({
createSearchChoice:function(term, data) {
if ($(data).filter(function() {
return this.text.localeCompare(term)===0;
}).length===0)
{return {id:term, text:term};}
},
multiple: false,
data: [{id: 0, text: 'story'},{id: 1, text: 'bug'},{id: 2, text: 'task'}]
});
Since many of these answers don't work in 4.0+, if you are using ajax, you could have the server add the new value as an option. So it would work like this:
User searches for value (which makes ajax request to server)
If value found great, return the option. If not just have the server append that option like this: [{"text":" my NEW option)","id":"0"}]
When the form is submitted just check to see if that option is in the db and if not create it before saving.
There is a better solution I think now
simply set tagging to true on the select options ?
tags: true
from https://select2.org/tagging
Improvent on #fmpwizard answer:
//Allow manually entered text in drop down.
createSearchChoice:function(term, data) {
if ( $(data).filter( function() {
return term.localeCompare(this.text)===0; //even if the this.text is undefined it works
}).length===0) {
return {id:term, text:term};
}
},
//solution to this error: Uncaught TypeError: Cannot read property 'localeCompare' of undefined
Thanks for the help guys, I used the code below within Codeigniter I I am using version: 3.5.2 of select2.
var results = [];
var location_url = <?php echo json_encode(site_url('job/location')); ?>;
$('.location_select').select2({
ajax: {
url: location_url,
dataType: 'json',
quietMillis: 100,
data: function (term) {
return {
term: term
};
},
results: function (data) {
results = [];
$.each(data, function(index, item){
results.push({
id: item.location_id,
text: item.location_name
});
});
return {
results: results
};
}
},
//Allow manually entered text in drop down.
createSearchChoice:function(term, results) {
if ($(results).filter( function() {
return term.localeCompare(this.text)===0;
}).length===0) {
return {id:term, text:term + ' [New]'};
}
},
});
I just stumbled upon this from Kevin Brown.
https://stackoverflow.com/a/30019966/112680
All you have to do for v4.0.6 is use tags: true parameter.
var text = 'New York Mills';
var term = 'new york mills';
return text.localeCompare(term)===0;
In most cases we need to compare values with insensitive register. And this code will return false, which will lead to the creation of duplicate records in the database. Moreover String.prototype.localeCompare () is not supported by browser Safary and this code will not work in this browser;
return this.text.localeCompare(term)===0;
will better replace to
return this.text.toLowerCase() === term.toLowerCase();
If I loop the collection in the view, it's seems empty, alert dialog don't show up. When I use console.log(this.collection) in this view, it's look ok (16 element in this collection).
My router: (collection url: '/api/employees', this is a rails json output)
Office.Routers.Employees = Backbone.Router.extend({
routes: {
"": "index"
},
initialize: function() {
this.collection = new Office.Collections.Employees();
this.collection.fetch();
},
index: function() {
var view = new Office.Views.EmployeesIndex({ collection: this.collection });
view.render();
}
});
and my index.js view:
Office.Views.EmployeesIndex = Backbone.View.extend({
render: function() {
this.collection.each( function( obj ){ alert(obj); } );
}
});
Edit:
This is the output of the console.log(this.collection) in view : http://i.stack.imgur.com/ZQBUD.png
Edit2:
I thing Rails is the guilty. When I work whit static collection, everything works fine
var collection = new Backbone.Collection([
{name: "Tim", age: 5},
{name: "Ida", age: 26},
{name: "Rob", age: 55}
]);
collection.fetch() makes an asynchronous request to the server. The index callback doesn't wait for the fetch to return. So your render function is rendering an empty collection.
You need to use the success callback of the fetch method:
index: function() {
this.collection.fetch({
success: function(data) {
var view = new Office.Views.EmployeesIndex({ collection: data });
view.render();
}
});
}
Note that the Backbone documentation recommends bootstrapping any initial data you need by including the data in the document itself:
When your app first loads, it's common to have a set of initial models
that you know you're going to need, in order to render the page.
Instead of firing an extra AJAX request to fetch them, a nicer pattern
is to have their data already bootstrapped into the page.
The fetch has probably not completed by the time your view renders. Try the following:
index: function() {
var p, collection, view;
collection = new Office.Collections.Employees();
p = collection.fetch();
view = new Office.Views.EmployeesIndex({ collection: collection });
p.done(view.render);
}
public ActionResult DoSomething(string[] arr, bool someBool, int someInt) { }
trying to call the above method from jQuery:
var test = [];
test.push('dog');
test.push('cat');
$container.load('MyController/DoSomething',
{ 'arr[]': test, 'someBool': true, 'someInt': 1 },
function(response, status, xhr) {
// ...
});
the array paramater is null, other params are fine. What am I doing wrong?
Chrome developer tools shows form data being submitted as
arr%5B%5D%5B%5D:dog
arr%5B%5D%5B%5D:cat
someBool:true
someInt:1
not sure whats going on there but doesn't look right to me
If you are using jquery 1.4 you might need to set the traditional parameter to true in order to be compatible with the default model binder format in ASP.NET MVC:
var test = [];
test.push('dog');
test.push('cat');
$.ajax({
url: 'MyController/DoSomething',
type: 'GET',
traditional: true,
data: { arr: test, someBool: true, someInt: 1 },
success: function(result) {
$container.html(result);
}
});
or if you prefer the .load() method:
var data = { arr: test, someBool: true, someInt: 1 };
$container.load('MyController/DoSomething', $.param(data, true),
function(response, status, xhr) {
// ...
});
Just remove []
{ 'arr': test, 'someBool': true, 'someInt': 1 },
Posted values (checking with Firebug).
arr[] dog
arr[] cat
someBool true
someInt 1
Example on jsFiddle
can you see if this problem is similar to yours:
Passing an nested arrays to asp.net mvc using jQuery's $.ajax
Even i was facing error, in passing array from HTML page to aspx page.
my requirement was to load the aspx page in a DIV tag of the html page. on the page load i need to pass these JS array values to aspx page load.
i used below method.
$('#<divTagID>').load("Targetpage.aspx",{"Arr":JSArrValues});
In aspx page load event i can access this values as:
string results = Response["Arr[]"];
Thanks to JQuery API documentation enter link description here and stackoverflow