dojo dstore insert row - javascript

Can anyone assist me in inserting a row into a DGRID? The way I am doing it now is cloning a row, add it to the collection with the use of directives and then try to apply it to the grid. Below is the code I am using but the new row ends up getting added to the bottom instead of being inserted.
// Clone a row
theTable = tmxdijit.registry.byId(tableName);
firstRow = theTable.collection.data[theTable.collection.data.length-1];
firstRowDom = theTable.row(firstRow.id);
var cloneRow = json.stringify(firstRow);
cloneRow = json.parse(cloneRow);
// Get the row I want to add before
var theSelected = Object.keys(theTable.selection)[0];
if(theSelected.length > 0) {
var theRowID = theSelected[0];
}
theTable.collection.add(cloneRow, {beforeId: theRowID});
theTable.renderArray([cloneRow]);

There are two general ways to handle data insertion. One is to manually add data to an array, ensure it's properly sorted, and then tell the grid to render the array. A better way is to use an OnDemandGrid with a trackable store.
For dgrid/dstore to support simple dynamic insertion of rows, make sure the store is trackable, and that data items have some unique id property:
var StoreClass = Memory.createSubclass(Trackable);
var store = new StoreClass({ data: whatever });
var grid = new OnDemandGrid({
columns: { /* columns */ },
collection: store
});
By default dstore assumes the id property is "id", but you can specify something else:
var store = new StoreClass({ idProperty: "name", data: whatever });
If you want the data to be sorted, a simple solution is to set a sort on the grid (the grid will sort rows in ascending order using the given property name):
grid.set('sort', 'name');
To add or remove data, use the store methods put and remove.
var collection = grid.get('collection');
collection.put(/* a new data item */);
collection.remove(/* a data item id */);
The grid will be notified of the store update and will insert or remove the rows.
The dgrid Using Grids and Stores tutorial has more information and examples.

Instead of this, why don't you add the data directly to the grid store? See if this helps
https://dojotoolkit.org/reference-guide/1.10/dojox/grid/example_Adding_and_deleting_data.html
Adding and Deleting data
If you want to add (remove) data programmatically, you just have to add (remove) it from the underlying data store. Since DataGrid is “DataStoreAware”, changes made to the store will be reflected automatically in the DataGrid.
dojo.require("dojox.grid.DataGrid");
dojo.require("dojo.data.ItemFileWriteStore");
dojo.require("dijit.form.Button");
.
<div>
This example shows, how to add/remove rows
</div>
<table data-dojo-type="dojox.grid.DataGrid"
data-dojo-id="grid5"
data-dojo-props="store:store3,
query:{ name: '*' },
rowsPerPage:20,
clientSort:true,
rowSelector:'20px'
style="width: 400px; height: 200px;">
<thead>
<tr>
<th width="200px"
field="name">Country/Continent Name</th>
<th width="auto"
field="type"
cellType="dojox.grid.cells.Select"
options="country,city,continent"
editable="true">Type</th>
</tr>
</thead>
</table>
<div data-dojo-type="dijit.form.Button">
Add Row
<script type="dojo/method" data-dojo-event="onClick" data-dojo-args="evt">
// set the properties for the new item:
var myNewItem = {type: "country", name: "Fill this country name"};
// Insert the new item into the store:
// (we use store3 from the example above in this example)
store3.newItem(myNewItem);
</script>
</div>
<div data-dojo-type="dijit.form.Button">
Remove Selected Rows
<script type="dojo/method" data-dojo-event="onClick" data-dojo-args="evt">
// Get all selected items from the Grid:
var items = grid5.selection.getSelected();
if(items.length){
// Iterate through the list of selected items.
// The current item is available in the variable
// "selectedItem" within the following function:
dojo.forEach(items, function(selectedItem){
if(selectedItem !== null){
// Delete the item from the data store:
store3.deleteItem(selectedItem);
} // end if
}); // end forEach
} // end if
</script>
</div>
.
#import "{{ baseUrl }}dijit/themes/nihilo/nihilo.css";
#import "{{ baseUrl }}dojox/grid/resources/nihiloGrid.css";

Related

Issues with getting object vars through a string

Not sure if the title makes sense but, I want to send data with an click event, this click event will get the data from a pre set var (in this case product101), as this var is formatted in JSON I cant seem to retrieve the data, it always returns a undefined. As the var is an object, but when I use the dataset var is an string right?
// inside a loop
<div class="container">
<script> var product<?=$id?> = {"category":"cars"}</script>
<div data-my-product="product<?=$id?>">
//all the product stuff
</div>
</div>
//located in the footer
$('[data-my-product]').click(function(){
//demo
var pro = $(this).data('my-product');
alert(pro.category);//returns undefined
})
When I click the product it returns a 'undefined' alert message.
Notice that the products are generated inside a loop.
Overview
Your best bet here is to create an object or Map with the things you want to look up this way, and then put them on it as properties or entries.
With an object:
var items = {
product101: {category: "cars"}
};
or if you want to be paranoid about the default inherited properties that exist on objects, you might use an object with no prototype:
var items = Object.create(null);
items.product101 = {category: "cars"};
then in your click handler:
alert(items[pro].category);
Live Example:
$('[data-my-product]').click(function() {
var pro = $(this).data('my-product');
alert(items[pro].category);
});
<div class="container">
<script>
var items = {
product101: {category: "cars"}
};
</script>
<div data-my-product="product101">
//all the product stuff
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
With a Map:
var items = new Map([
["product101", {category: "cars"}]
]);
then in your click handler:
alert(items.get(pro).category);
Live Example:
$('[data-my-product]').click(function() {
var pro = $(this).data('my-product');
alert(items.get(pro).category);
});
<div class="container">
<script>
var items = new Map([
["product101", {category: "cars"}]
]);
</script>
<div data-my-product="product101">
//all the product stuff
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Side note: Although you can access that data-* attribute's value (indirectly) using data, doing so sets up a data cache for the element and initializes that cache with the attribute's value. If you're just looking to get the string, .attr("data-my-product") is more direct. See this answer for more details.

Using API result to create another request and display them together

I'm having trouble retrieving some data from an API, the server provides JSON data as follows:
http://segue-api.fisl16.softwarelivre.org/api/rooms/1/slots
http://segue-api.fisl16.softwarelivre.org/api/talks/526 (the number is the talk id)
I need to create a table to visualize the data that is relevant to me. So I created a simple JS function to retrieve information from the first link (/rooms/1/slots) and feed an HTML table (the code is below).
Using the ID I can gather from the first function I want to make another request to the API (/talks/"id") and display the results on the same row as the ID.
The final result would be the table from the snippet with a new column called "description" which contains the description available on the API (/talks/"id") on the same row as the "id".
I'm clueless, any ideas?
var room1 = "http://segue-api.fisl16.softwarelivre.org/api/rooms/1/slots"
$.getJSON(room1,function(data){
$.each(data.items, function(){
$("#table").append("<tr><td>"+this['begins']+"</td><td>"+this['talk'].id+"</td><td>"+this['duration']+"</td><td>"+this['talk'].title+"</td><td>"+this['talk'].owner+"</td><td>"+this['talk'].coauthors+"</td><td>"+this['room_name']+"</td>");
});
});
table, th, td {
border: 1px solid black;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<table id="table">
<th>Data e Hora</th>
<th>Id</th>
<th>Duração</th>
<th>Título</th>
<th>Palestrante</th>
<th>co-palestrantes</th>
<th>sala</th>
</table>
If you can not get the data from the second API for many ID at once, it can be in a loop to make subqueries ( http://jsfiddle.net/tmjvzo63/ ):
room1 = "http://segue-api.fisl16.softwarelivre.org/api/rooms/1/slots";
$.getJSON(room1,function(data){
$.each(data.items, function(){
var rid = "r"+this['talk'].id;
$("#table").append("<tr id='"+rid+"'></tr>");
$("#"+rid).append("<td>"+this['begins']+"</td><td>"+this['talk'].id+"</td><td>"+this['duration']+"</td><td>"+this['talk'].title+"</td><td>"+this['talk'].owner+"</td><td>"+this['talk'].coauthors+"</td><td>"+this['room_name']+"</td>");
var rj = "http://segue-api.fisl16.softwarelivre.org/api/talks/"+this['talk'].id;
$.getJSON(rj,function(data){
console.log(data.resource.id);
$("#r"+data.resource.id).append("<td>"+data.resource.full+"</td>");
});
});
});
You could do something like
$.getJSON(room1,function(data){
$.each(data.items, function(){
var row = item;
$.getJSON("http://segue-api.fisl16.softwarelivre.org/api/talks/" + item["talk"].id, function(dataItem){
var $table = $("#table");
if ($table.find("th:last").text() !== "Description") { //Or whatever it is named
$table.find("th:last").after("<th>Description</th>"); //This creates the TH if it doesn't exist
}
$table.append("<tr><td>"+item['begins']+"</td><td>"+item['talk'].id+"</td><td>"+item['duration']+"</td><td>"+item['talk'].title+"</td><td>"+item['talk'].owner+"</td><td>"+item['talk'].coauthors+"</td><td>"+item['room_name']+"</td><td>" + dataItem.description + "</td>");
})
})
});

delete row(s) from ng-grid table from button

I have a table with ng-grid, and the problem is that i'm not sure how to collect the selected row(s) id or variable to pass into my delete function.
here is a quick mockup of what i'm trying to do
http://plnkr.co/edit/zy653RrqHmBiRJ7xDHlV?p=preview
the following code is from my html, a clickable delete button that takes in 2 parameters, the array of checkbox ids and the index at the corresponding table. This delete method was obtained from this tutorial : http://alexpotrykus.com/blog/2013/12/07/angularjs-with-rails-4-part-1/
<div class="btn-group">
<button class="my-btn btn-default button-row-provider-medical-services" ng-click="deleteProviderMedicalService([], $index)">Delete</button>
</button>
</div>
<div class="gridStyle ngGridTable" ng-grid="gridOptions">
</div>
The following code grabs the json data from a url, queries it and returns it. It also contains the delete function that gets called from the controller in the html page.
app.factory('ProviderMedicalService', ['$resource', function($resource) {
function ProviderMedicalService() {
this.service = $resource('/api/provider_medical_services/:providerMedicalServiceId', {providerMedicalServiceId: '#id'});
};
ProviderMedicalService.prototype.all = function() {
return this.service.query();
};
ProviderMedicalService.prototype.delete = function(providerId) {
this.service.remove({providerMedicalServiceId: providerId});
};
return new ProviderMedicalService;
}]);
The following is my controller(not everything, just the most important bits). $scope.provider_medical_services gets the json data and puts it into the ng-grid gridOptions.
After reading the ng-grid docs, i must somehow pass the checkbox ids from the selectedItems array and pass it into html doc to the delete function. Or, i'm just doing this completely wrong, as i hacked this together. Solutions and suggestions are greatly appreciated
(function() {
app.controller('ModalDemoCtrl', ['$scope', 'ProviderMedicalService', '$resource', '$modal', function($scope, ProviderMedicalService, $resource, $modal) {
var checkBoxCellTemplate = '<div class="ngSelectionCell"><input tabindex="-1" class="ngSelectionCheckbox" type="checkbox" ng-checked="row.selected" /></div>';
$scope.provider_medical_services = ProviderMedicalService.all();
$scope.deleteProviderMedicalService = function(ids,idx) {
$scope.provider_medical_services.splice(idx, 1);
return ProviderMedicalService.delete(ids);
};
$scope.gridOptions = {
columnDefs: [
{
cellTemplate: checkBoxCellTemplate,
showSelectionCheckbox: true
},{
field: 'name',
displayName: 'CPT Code/Description'
},{
field: 'cash_price',
displayName: 'Cash Price'
},{
field: 'average_price',
displayName: 'Average Price'
},
],
data: 'provider_medical_services',
selectedItems: []
};
i think the easiest option is pass an (array index) as data-id to your dom, which u can pick it from there.
{{$index}} is a variable you can use in ng-repeat
======= ignore what i said above, since i normaly writes my own custom stuff ======
I just had a look at ng-grid, i took their example. i've added a delete all selected function, as well as someone elses delete current row function ( these is pure angular way ) to see the code, hover over the top right corner < edit in jsbin >
http://jsbin.com/huyodove/1/
Honestsly i don't like it this way, you would be better off use something like lodash to manage your arrays and do your own custom grid. Using foreach to find the row index isn't good performance.
In their doc, it says you can change the row template, and which you should, so you can add the {{index}} to that row, and filter your data through that index rather which is a little bit better. anyway beware of deleting cells after you have filter your table.
I don't quite get much your question, but you can access to selectedItems of ng-grid as following: $scope.gridOptions.$gridScope.selectedItems (see ng-grid API for more information, but technically this array holds the list of selected items in multiple mode - or only one item in single mode)
For your case, the deleteAll() function could be someething like this:
$scope.deleteAll = function() {
$scope.myData = [];
}
The delete() function which delete selected items can be:
$scope.delete = function() {
$.each($scope.gridOptions.$gridScope.selectedItems, function(index, selectedItem) {
//remove the selected item from 'myData' - it is 2-ways binding to any modification to myData will be reflected in ng-grid table
//you could check by either name or unique id of item
});
}

Angular JS : creating table with json

I've created an application in angular-JS for creating table with dynamic columns from json
For example the JSON structure returning from a service is in the structure where the others field of the main JSON contains another JSON array which is the additional columns,
so all together there will be four additional dynamic columns i.e File 1, File 2, File 3, File 4 each object has value for the corresponding File field, sometime present sometime not present.
$scope.getColumns = function()
{
//console.log( $scope.datas[0].others[0]);
$scope.datas.resultsOrder = new Array();
for ( var i = 0; i < $scope.datas.length; i++)
{
for ( var j = 0; j < $scope.datas[i].others.length; j++)
{
if (countInstances($scope.datas.resultsOrder, $scope.datas[i].others[j].id) < countInstances(
$scope.datas[i].others, $scope.datas[i].others[j].id)){
$scope.datas.resultsOrder.push($scope.datas[i].others[j].id);
}
}
}
$scope.datas.resultsOrder.sort(function(a, b){
return a.localeCompare(b);
});
return $scope.datas.resultsOrder;
}
I've shown the tables with the dynamic columns perfectly using javascript help, but can anyone please tell me some other way for creating the above dynamic table through angular js in a simple way, since in my code I've used javascript complex logic for the creation of dynamic columns which is as shown below
My JS-Fiddle is given below
Demo
This wll create an object called columns where the properties are the names of the dynamic columns ('File 1', 'File 2' etc.)
Controller:
$scope.columns = {};
angular.forEach( $scope.datas, function(data){
angular.forEach( data.others, function(other){
// Set the 'File x' property for each item in the others array
data[other.id] = other.value;
// Add the dyanmic column to the columns object
$scope.columns[other.id] = null;
});
});
View:
<!-- table header -->
<tr>
<th ng-repeat="(column,val) in columns">
<a ng-click="sort_by()"><i>{{column}}</i></a>
</th>
....
</tr>
<!-- data rows -->
<td ng-repeat="(column,v) in columns">{{val[column]}}</td>
Fiddle

Dynamically creating kendo-grid columns in angular controller

I am trying to dynamically build the structure of a kendo-angular grid. My problem is that the grid options are not known when the k-options attribute is evaluated, so the grid is binding to ALL of the columns on the datasource.
Here is the HTML:
<div kendo-grid k-options="{{gridModel.options}}"
k-data-source="gridModel.myDataSource">
</div>
And here is the javascript in the controller:
// this is called after the api call has successfully returned with data
function getSucceeded(){
...
$scope.gridModel.options = function(){
// function that properly builds options object with columns, etc.
}
// this is just shown for example... the data is properly loading
$scope.gridModel.myDataSource.data(ds.data());
}
The data is properly loading, but because gridModel.options was evaluated in the HTML prior to being set by the success method, it is essentially ignored and all of the columns from the datasource are being rendered.
This works like a champ when gridModel.options is static.
How can I defer the evaluation of k-options and/or force a reevaluation after they've been set by the controller?
I was able to figure it out. I had to do four things:
Update my version of angularjs (I was on 1.08 which does not have the ng-if directive). I updated to 1.2.0rc3.
Wrap my kendo-grid div in an ng-if div
Invoke my function! I was just setting $scope.gridModel.options to a function - I needed to actually invoke the function so I'd be setting the variable to the value returned from the function.
I had to update my angular.module declaration to include ngRoute (based on it being separated into it's own module in 1.2.x).
Here's the updated HTML:
<div data-ng-if="contentAvailable">
<div kendo-grid k-options="{{gridModel.options}}"
k-data-source="gridModel.myDataSource">
</div>
</div>
And here's the updated controller (not shown: I set $scope.contentAvailable=false; at the beginning of the controller):
// this is called after the api call has successfully returned with data
function getSucceeded(){
...
$scope.gridModel.options = function(){
// function that dynamically builds options object with columns, etc.
}(); // <----- NEED to invoke function!!
// this is just shown for example... the data is properly loading
$scope.gridModel.myDataSource.data(ds.data());
$scope.contentAvailable=true; // trigger the ng-if
}
I actually moved the function into a config file so I'm not polluting the controller with too much configuration code. Very happy to have figured this out.
Here is a sample using 'Controller As' syntax, dynamic columns and paging.
var app = angular.module("app", ["kendo.directives"]);
function MyCtrl() {
var colsList = [{
name: "col1"
}, {
name: "col2"
}, {
name: "col3"
}, {
name: "col4"
}];
var gridCols = [];
var iteration = 1;
var vm = this;
vm.gridOptions = {
columns: gridCols,
dataSource: new kendo.data.DataSource({
pageSize: 10
}),
pageable: true
};
vm.buildGrid = function() {
var data = {};
vm.gridOptions.columns = [];
for (var x = 0; x < colsList.length; x++) {
if (iteration % 2 === 0 && x === colsList.length - 1) continue;
var col = {};
col.field = colsList[x].name;
col.title = colsList[x].name;
data[col.field] = "it " + iteration + " " + (1111 * (x + 1));
vm.gridOptions.columns.push(col);
}
// add one row to the table
vm.gridOptions.dataSource.add(data);
iteration++;
};
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<link rel="stylesheet" href="http://cdn.kendostatic.com/2015.1.318/styles/kendo.common.min.css" />
<link rel="stylesheet" href="http://cdn.kendostatic.com/2015.1.318/styles/kendo.default.min.css" />
<script src="http://cdn.kendostatic.com/2015.1.318/js/kendo.all.min.js"></script>
<body ng-app="app">
<div ng-controller="MyCtrl as vm">
<button ng-click="vm.buildGrid()">Build Grid</button>
<div kendo-grid="grid" k-options="vm.gridOptions" k-rebind="vm.gridOptions"></div>
</div>
</body>
We can use the k-rebind directive for this. From the docs:
Widget Update upon Option Changes
You can update a widget from controller. Use the special k-rebind attribute to create a widget which automatically updates when some scope variable changes. This option will destroy the original widget and will recreate it using the changed options.
Apart from setting the array of columns in the GridOptions as we normally do, we have to hold a reference to it:
vm.gridOptions = { ... };
vm.gridColumns = [{...}, ... ,{...}];
vm.gridOptions.columns = vm.gridColumns;
and then pass that variable to the k-rebind directive:
<div kendo-grid="vm.grid" options="vm.gridOptions" k-rebind="vm.gridColumns">
</div>
And that's it when you are binding the grid to remote data (OData in my case). Now you can add or remove elements to/from the array of columns. The grid is going to query for the data again after it is recreated.
When binding the Grid to local data (local array of objects), we have to somehow postpone the binding of the data until the widget is recreated. What worked for me (maybe there is a cleaner solution to this) is to use the $timeout service:
vm.gridColumns.push({ ... });
vm.$timeout(function () {
vm.gridOptions.dataSource.data(vm.myArrayOfObjects);
}, 0);
This has been tested using AngularJS v1.5.0 and Kendo UI v2016.1.226.

Categories

Resources