I want to remove an object from an ko.observableArray
I have two observableArrays
self.arrayA = ko.observableArray();
self.arrayB = ko.observableArray();
then in a function I want to remove an item.
self.myRemoval = function(item){
var arrayToRemoveFrom;
if ( somelogic ) {
arrayToRemoveFrom = self.arrayA();
}
else {
arrayToRemoveFrom = self.arrayB();
}
arrayToRemoveFrom.remove(item);
}
The line "arrayToRemoveFrom.remove(item)" causes an exception, saying remove is not a function. What would be the best way to remove "item"?
remove is a special function of the ko.onservableArray .
However when you write self.arrayA(); with the () at the end you are returning the underlaying JavaScript array which does not have a remove function and you get the exception.
To fix your code you just need to remove the ():
self.myRemoval = function(item){
var arrayToRemoveFrom;
if ( somelogic ) {
arrayToRemoveFrom = self.arrayA;
}
else {
arrayToRemoveFrom = self.arrayB;
}
arrayToRemoveFrom.remove(item);
}
Related
For the code below, I wanted to make the _formsOk function work for both Javascript arrays and "JQuery objects". In function1(), I tried to create a Javascript array with all DOM elements except those that have a parent element with id="objectTypesContainer". Basically, function1() filters out the DOM elements I don't want before calling _formsOk() function, which does the actual form validation.
function1() {
var allForms = $('form:not(.vv_hidden)', this.selectMarketsContainer);
var nonObjectTypeForms = [];
allForms.each(function () {
if ($(this).parent().attr("id") !== "objectTypesContainer"){
nonObjectTypeForms.push($(this)[0]);
}
});
return this._formsOk(nonObjectTypeForms);
},
_formsOk: function($forms) {
var formOk = true;
console.log(typeof $forms)
$forms.each(function () { // This line fails
var validator = $(this).validate(DEFAULT_VALIDATION_OPTIONS);
if (!(validator && validator.form())) {
formOk = false;
}
});
return formOk;
},
However, I realized that because nonObjectTypeForms is now a JS Array rather than a "JQuery Object", the line marked (// This line fails) now fails.
The original code looked like this:
function1() {
var allForms = $('form:not(.vv_hidden)', this.selectMarketsContainer); // This is a "JQuery object", so no error occurs
return this._formsOk(allForms);
},
_formsOk: function($forms) {
var formOk = true;
console.log(typeof $forms)
$forms.each(function () { // This line fails
var validator = $(this).validate(DEFAULT_VALIDATION_OPTIONS);
if (!(validator && validator.form())) {
formOk = false;
}
});
return formOk;
},
Is there a way I can convert a JS array into a JQuery object ? I don't want to change _formsOk function definition just yet.
Instead of putting all elements in a new array, just use .filter() from the jQuery object.
allForms.filter(function () {
return $(this).parent().attr("id") !== "objectTypesContainer")
});
This will remove all the items you don't need in your selection and now allForms will only have the wanted elements.
i have understand that i need to change the global scope of this, because in the loop this refers to the window object. But if i try to define a variable in my foreach loop via a function its not working and i dont know why although my functio returns the correct value :(
// simple class for xml import
function io() {
this.vertexes = [];
this.getVertexByID = function(id) {
this.vertexes.forEach(function(entry) {
if (id == entry.id) {
// correct element found, displayed and returned
console.log(entry);
return entry;
}
});
}
this.importXML = function(xmlString) {
cells = this.xmlToJson(xmlString);
var parent = graph.getDefaultParent();
var _this = this;
graph.getModel().beginUpdate();
try {
// addEdges
cells.XMLInstance.Edges.Relation.forEach(function(entry) {
// both will be empty but i dont understand why :(
fromVertex = _this.getVertexByID(entry.fromNode);
toVertex = _this.getVertexByID(entry.toNode);
var e1 = graph.insertEdge(parent, null, '', fromVertex, toVertex);
});
} finally {
graph.getModel().endUpdate();
}
}
Returning a value in a forEach callback has no effect. It certainly is not the return value of the function that the forEach is part of.
So change this:
this.vertexes.forEach(function (entry) {
if(id==entry.id){
//correct element found,displayed and returned
console.log(entry);
return entry;
}
});
to this:
return this.vertexes.find(function (entry) {
return id==entry.id;
});
I'm trying to get either options or, ideally, dynamicTable passed from initializeTable to the applyTableFilters function and I'm having problems getting the expected values. I'm using List.js to make a table dynamic and I need to pass or recreate the dynamicTable object so I can go ahead and use it to filter the table.
Here is the function that creates the List.js object from the HTML table:
function initializeTable(options) { // initializes table to be dynamic using List.js functions
var dynamicTable = new List("table-content", options);
dynamicTable.on("updated", function (list) { // writes a message to the user if no results are found
if (list.matchingItems.length == 0) {
document.getElementById("no-results").style.display = "block";
}
else {
document.getElementById("no-results").style.display = "none";
}
});
console.log(dynamicTable);
console.log(options);
console.log(arguments.length);
applyTableFilters.bind();
}
I've tried different methods to pass the variables to the function below. I tried .call, applyTableFilters(args), and .apply, but the problem is that I do not want the function to execute from inside here, only when the click event from the button goes off (not shown in these functions).
This is the function I want to pass the object to and proceed to make the filter functions using it:
function applyTableFilters(dynamicTable) {
var form = document.getElementById("filter-form");
//console.log(options);
//var dynamicTable = new List("table-content", options);
console.log(dynamicTable);
var filters = form.querySelectorAll('input[type="checkbox"]:checked');
dynamicTable.filter(function (item) {
console.log(item);
console.log(item._values);
if (item.values().id == 2) {
return true;
}
else {
return false;
}
//var filterStrings = [];
//console.log(filters);
//for (var i = 0; i < filters.length; i++) {
// var filterVal = filters[i].value;
// var filterString = "(" + item.values().column == filterVal + ")"; // filterVal.contains(item.values().column) ||
// filterStrings.push(filterString);
// console.log(filterVal);
// console.log(filterString);
//}
//console.log(filterStrings);
//var filterString = filterStrings.join(" && ");
//console.log(filterString);
//return filterString;
});
}
I've used:
applyTableFilters.bind(this, dynamicTable/options);
applyTableFilters.bind(null, dynamicTable/options);
applyTableFilters.bind(dynamicTable/options);
Switching between the two since I don't need both passed if one ends up working, etc. I always get a mouse event passed in and that's not even the right type of object I'm looking for. How can I get the right object passed? Also all the values in the first function are not empty and are populated as expected so it's not the original variables being undefined or null. Thanks in advance.
From your initializeTable function return a function that wraps the applyTableFilters function with the arguments you want.
Then assign the returned function to a var to be executed later.
function initializeTable(options) {
var dynamicTable = new List("table-content", options);
// other stuff
return function () {
applyTableFilters(dynamicTable)
}
}
// other stuff
var applyTableFiltersPrep = initializeTable(options)
// later, when you want to execute...
applyTableFiltersPrep()
JSFiddle example
I have the object words and a checkbox which should hide a specific element from this object, but I cannot get it work.
<body ng-controller="ArrController">
<input type="checkbox" ng-model="hide"> {{kc}}
{{words}}
</body>
The ArrController:
app.controller('ArrController', function ($scope, $http) {
$scope.hide = false;
$http.get('array.json').success(function(data) {
var keyword = 'lol';
$scope.words = data.unsorted_arr;
$scope.$watch('hide', function () {
if ($scope.hide == true) {
var remove = function() {
$scope.words.splice(keyword, 1);
}
$scope.kc = 'hidden';
} else {
$scope.kc = 'not hidden';
$scope.words = data.unsorted_arr;
}
});
});
});
The file array.json contains data for words:
{"unsorted_arr":{"gonna":3,"lol":114,"wouldn":2,"know":6,"lowkey":2,"man":5}}
The kc modifies according to the checkbox status, but the words stays the same.
Where am I wrong?
Splice is for removing something in an array, and it takes in two integers as parameters.
Since you have an object, just use delete:
delete $scope.words[keyword];
By doing, $scope.words = data.unsorted_arr, the two variables refer to the same object so deleting something from $scope.words will delete it from data.unsorted_arr.
Keep a reference to it so you can repopulate it later:
var word = $scope.words[keyword];
...
delete $scope.words[keyword];
...
$scope.words[keyword] = word;
You are confusing Indexed arrays with associative arrays,
Array.splice is a method of Indexed Arrays,
you have a simple Javascript Object (associative array)...
on POJO you can use the delete operator or a simply reassignment to undefined:
var a = { foo: 'baz' };
delete a['foo'];
var b = ['foo', 'baz'];
b.splice(0, 1)
In your example you are defining a function for removing the element, but the function is never being called.
var remove = function() {
$scope.words.splice(keyword, 1);
}
you may need to your logic to remove the function (as it doesn't seem to be needed) and replace the of use splice with the delete statement:
$http.get('array.json').success(function(data) {
var keyword = 'lol';
$scope.words = data.unsorted_arr;
$scope.$watch('hide', function () {
if ($scope.hide == true) {
delete $scope.words[keyword];
$scope.kc = 'hidden';
} else {
$scope.kc = 'not hidden';
$scope.words = data.unsorted_arr;
}
});
});
I'm not really sure why my code isn't running correctly.. what I'm trying to do is create a grocery list object that has a couple of functions to add and remove items..
I can instantiate the objects with new items but my functions don't seem to work for some reason.
If you could save me the few hairs left in my head and tell me where the issue is I would greatly appreciate it.
var groceryList = function(itemNames,quantity) {
if (Array.isArray(itemNames)) {
this.items = itemNames;
this.quantity = quantity
this.addItems = function(newItems){
if ( Array.isArray(newItems) ) {
this.items.concat(newItems);
} else {
console.log("Please enter the items in an array fashion!");
};
};
this.removeItem = function(name) {
var listSize = this.items.length;
for (var i = 0; i < listSize; i++) {
if (this.items[i] == name) {
this.items.splice(i,1);
break;
} else {
console.log("Please enter the items in an array fashion!")
};
};
};
} else {
console.log("Please enter the items in an array fashion!")
};
};
.concat() returns a new array so you have to assign the result back to your instance variable.
So this:
this.items.concat(newItems);
needs to be changed to this:
this.items = this.items.concat(newItems);
or, you could actually use this to append to the array directly:
this.items.push.apply(this.items, newItems);
Because .push() can take more than one argument.
Then, in your .removeItem() function, you need to remove the item you actually found by changing this:
this.items.splice(2,1);
to this:
this.items.splice(i,1);