I need to access the members of viewmodel object in a javascript function and have tried to do this by assigning it to a jscript variable like this:
var teamEdit = (function() {
return {
communityGroups: '#Model.CommunityGroups'
}
});
$(function() {
....
var groups = teamEdit.communityGroups;
Unfortunately the groups variable comes out as undefined even though 'CommunityGroups' is defintely populated. (checked by debugging controller)
#Model.CommunityGroups would simply call ToString() that would emit something like "System.Collections.Generic.List`1[CommunityGroup]".
You need to serialize it to JSON instead:
communityGroups: #Html.Raw(Json.Encode(Model.CommunityGroups))
The issue with your code was you were try to access the function teamEdit with out () change it to teamEdit()
See the below.
var teamEdit = (function() {
return {
communityGroups: '#Model.CommunityGroups'
}
});
$(function() {
....
var groups = teamEdit().communityGroups;
Related
Is it possible to store the reference to an element in an array or object without having a unique ID on the element?
I am having trouble with storing a subtable in another table so I can reference it later. I get the table by class with this code:
$(this).parent('tr').parent().find('.tableSomeTable');
Is the only solution to have unique id's on each element and use the .selector method?
More of my code. Abit simplified.
var rows = [];
var historyLoad;
$(document).on("click", '.details-control', function (e) {
var t = $(this);
var tr = t.closest('tr');
var row = t.parent().parent().parent().DataTable().row(tr);
var id = t.closest('tr').attr('id');
var object = {
id: id,
btnHistory: t.parent('tr').next().find('#btnHistory'),
tblHistory: t.parent('tr').parent().find('.tableHistory'),
historyLoad: historyLoad
};
if ($.inArray(id, rows) > -1) {
loadData = false;
}
else {
loadData = true;
loadHistory(object);
rows.push(object);
}
};
Here is where I am having trouble retrieving the correct elements. And I also want to save the ajaxHistory element to my object (which is working fine).
This code is not working, but if I change it to $(result.btnHistory.btnHistory.selector) I get the object. But this doesn't seem to work very good with multiple rows.
function loadHistory(result) {
result.ajaxHistory = $.ajax({
...
beforeSend: function () {
$(result.btnHistory).html(<loading txt>);
$(result.tblHistory).find('tbody').html(<loading txt>);
},
....
success: function (data) {
if (data.TotalRecordCount > 0) {
$(result.tblHistory).find('tbody').html('');
$.each(data.Records, function (e, o) {
$(result.tblHistory).find('tbody').append(<data>)
});
}
else {
$(result.tblHistory).find('tbody').html(<txt no records>);
}
$(result.btnHistory).html(<txt loading done>));
},
First off, if you are trying to find the parent table, try
var $myObj = $(this).closest('table.tableSomeTable');
instead of navigating parents.
As far as storing the jQuery reference, define a variable and then store it. The above will store the object in $myObj but that is locally scoped. If you need a global variable then define it globally and just assign it here. If you want to define it as a property within an object then define it that way. It really comes down to a scope question at this point.
EDIT: Just saw your added content.
First off, don't name it 'object'. This may run into key word issues. Use var myObj or similar instead. Next, object.btnHistory is a reference to a jQuery object. So, when you pass it to loadHistory, you do not need to apply the $(...) again. Just use the reference directly: result.btnHistory.html(...). A good habit to get into is prepending you jQuery variables with $ so you remember it is already a jQuery variable.
The .find() method returns a jQuery object. So the answer is, yes, you can store this return object in a variable:
var $yourObject = $(this).parent('tr').parent().find('.tableSomeTable');
I have an json object which I am responding from servlet to knockout js. I want to initialize this data in my view model for that I am writing this code.
success: function (data)
{
var jsondata = data['jsonObj'];
self.PopulateStates = ko.computed(function(){
ko.utils.arrayForEach(jsondata, function(item){
self.States.push(new State(item));
});
});
},
error: function (exception)
{
alert( "fail" );
}
});
My json object as string looks like this
{data:[{"id":"5345345","name":"dsfsdf","ssc":"","bic":"dgffdgfdg"},{"id":"123456","name":"SBI","ssc":"654321","bic":"vxvxc"}]}
js fiddle link is demo
What is my mistake ? Or do I need to do it by mapping plugin of knockout js?
I use this knockout extension, declared before use.
ko.observableArray.fn.map = function (data, Constructor) {
var mappedData = ko.utils.forEach(data, function () {
return new Constructor(data);
});
this(mappedData);
return this;
}
Then in my $.ajax request I do this:
success: function (data)
{
var jsondata = data['jsonObj'];
self.PopulateStates = ko.observableArray().map(data, State);
});
You had the results in a computed observable which isn't what you need.
Another thing I have noticed is that your jsondata is set using the data that gets returned from the GET. You are asking that data for the field jsonObj however, looking at your JSON it seems you don't have this field. I think I am correct in saying you have data as the field with the list of items being returned.
If in your view model you have already declared self.PopulateStates which, I'm guessing you have. You can do this:
var State = function (data) {
var self = this;
self.property = ko.observable().set(data, "property");
}
var viewModel = function () {
var self = this;
self.PopulateStates = ko.observable();
function getStates() {
var request = $.ajax();
request.done(function (data, msg) {
if (data) self.PopulateStates.map(data, State);
});
}
}
If you notice in the State model I have self.property using a custom observable function to set it. All this does is if there is data to set the property to, set it. Otherwise give it a default value. I also have a third parameter that I use when I want it to construct an object for me using the data. This is when I have say, a contact, with a modifiedBy property and this modifiedBy is a user object (or just a complex object)
EDIT
The main thing, which isn't an error, but isn't necessary is the jQuery inclusion. Knockout is built to work independant of jQuery so where you do $(document).ready(function () {}) to make sure this loads on DOM ready isn't needed. This means you don't have to include jQuery if the page doesn't need it.
Here is the update fiddle, this will now work!
update: This code is bonkers. The root of the issue here is recreating the name of a variable by concating strings and assuming it would then magically turn into that variable.. I had a lot to learn. Also, a much better way to pass an ambiguous number of options into a function is to use JSON.
var availableTimes,
selected_unit,
selected_unit_number;
function createTimePicker(machineNumber){
availableTimes = machineNumber({booked:"no"}).select("time");
for (i=0;i<availableTimes.length;i++){
$('<option/>').val(availableTimes[i]).html(availableTimes[i]).appendTo('#signin_start_time');
}
}
$(function() {
$('body').on('click', '#cybex_arctrainer_button', function() {
selected_unit = "cybex_arctrainer";
});
$('body').on('change', '#signin_unit_number_selector', function () {
selected_unit_number = $("#signin_unit_number_selector option:selected").text();
unit_plus_number = selected_unit+selected_unit_number;
createTimePicker(unit_plus_number);
});
});
A few things: The database works. If I run createTimePicker(cybex_arctrainer1) it fills in the availableTimes variable just fine. The problem seems to be with combining selected_unit+selected_unit_number and passing them to createTimePicker.
Here:
machineNumber({booked:"no"})
machineNumber is a string, but you're trying to call it as if it is a function. You'll get the same error if you do something like
someVar = 'bob';
someVar();
You say that if you run
createTimePicker(cybex_arctrainer1);
but your code is not calling createTimePicker with the variable cybex_arctrainer1 as an argument, instead it's doing something more like:
createTimePicker('cybex_arctrainer1');
I'm working on a code where I must pass a different function to some objects.
In this case, I'm trying to pass a different function for the onchange event. So currently what I got is something like this this:
var ArrayList; //Contains some data to use with ObjectArray format { n: data }
var ObjectArray; //Contains several objects format Array[n] = Object;
for(var key in ArrayList){
var doFunction = function() {
Object[key].doSomething(ArrayList[key]);
}
Object[key].onchange = doFunction;
}
The problem here I believe is that I'm afraid it will execute the code as it is declared and not with the values of the actual variables.
Is there a way to pass the function with the values as it executes? or will the variables get parsed the way its written?
It's the classic function in a loop problem. You need to understand how closures work.
Read the "Example 3" part of this answer carefully. The whole How do JavaScript closures work? question, too.
Another example that might help understand intuitively:
var key = 5;
var onchange = function () {
console.log(key);
};
onchange(); // 5
key = 10; // the loop reassigns the key on each iteration
onchange(); // 10
This is how it should be done:
var ArrayList; //Contains some data to use with ObjectArray format { n: data }
var ObjectArray; //Contains several objects format Array[n] = Object;
for(var key in ArrayList)
{
(function(key)
{
var doFunction = function()
{
Object[key].doSomething(ArrayList[key]);
}
Object[key].onchange = doFunction;
}(key))
}
I have a plugin that looks like this:
(function($) {
$.fn.plugin_name = function(options) {
var $this = $(this);
var defaults = {
// some defaults
};
options = $.extend({}, defaults, options);
var work = {
action_1: function() {
// do something
},
action_2: function(output) {
alert('hello world');
}
}
that.submit(function(e) {
e.preventDefault();
work.action_1();
});
return $this;
}
})(jQuery);
It's being used like any traditional jquery plugin, by being attached to a page element like so:
$('#search-form').plugin_name({
// overide options
});
My question is, how can I execute the work.action_2() function that's deeply nested inside the plugin? I would like to call it manually from the javascript console in firebug.
My question is, how can I execute the work.action_2() function that's deeply nested inside the plugin?
You can't, it's outside of your scope!
you can't reach private function variables, just like you can't reach my functions...
Create it in a separate utility function if its needed independently, better if its in your own global object.
So you can call it like so: $.myGlobalObj.action_2()