how to add custom field in jTable ASP.Net MVC - jquery-jtable

I would like to know how to add a custom field column in jTable ASP.net MVC. I will be adding an image icon that will have a link popup to my custom page.
Solved My Problem:
$('#Container').jtable({
...
actions: {
...
},
fields: {
TestField: {
title: ' ',
sorting: false,
display: function (data) {
return "Open details";
}
},
}
});

Related

Why is the apostrophe-pages _children array is always empty?

I am trying to get the children of apostrophe pages to appear in my navigation object - however the _children array is always empty. My page does have child pages set up via the front end Pages UI.
My index.js for the lib/modules/apostrophe-pages module contains the following:
construct: function(self,options) {
// store the superclass method and call at the end
var superPageBeforeSend = self.pageBeforeSend;
self.pageBeforeSend = function(req, callback) {
// Query all pages with top_menu setting = true and add to menu collection
self.apos.pages.find(req, { top_menu: true }, {slug: 1, type: 1, _id: 1, title: 1})
.children(true)
.toArray(
function (err, docs) {
if (err) {
return callback(err);
}
req.data.navpages = docs;
return superPageBeforeSend(req, callback);
});
};
},
...
My top_menu attribute is set via apostrophe-custom-pages:
module.exports = {
beforeConstruct: function(self, options) {
options.addFields = [
{
name: 'subtitle',
label: 'Subtitle',
type: 'string'
},
{
name: 'css_class',
label: 'CSS Class',
type: 'string'
},
{
name: 'top_menu',
label: 'Include In Top Menu',
type: 'boolean'
}
].concat(options.addFields || []);
}
};
This gives me the pages I need with the top_menu setting.. but I want to get child pages too..
When debugging the code I can see that the docs._children array is present but is always empty, even though a page has child pages...
I have tried adding the following both to my app.js and to my index.js but it doesn't change the result:
filters: {
// Grab our ancestor pages, with two levels of subpages
ancestors: {
children: {
depth: 2
}
},
// We usually want children of the current page, too
children: true
}
How can I get my find() query to actually include the child pages?
Solved it..
I needed to add 'rank: 1, path: 1, level: 1' to the projection as per this page in the documentation: https://apostrophecms.org/docs/tutorials/howtos/children-and-joins.html#projections-and-children

How to replace nested stack with other component in react-native-navigation v2?

I'm trying to build a dynamic wizard with react-native-navigation v2.
I say dynamic because the number of steps may vary depending on which options the user selects.
I was thinking to use nested stacks, so the layout of my app would look something like this:
{
root: {
sideMenu: {
left: {/*...*/},
center: {
stack: {
children: [component1, /*...,*/ componentX]
}
}
}
}
}
ComponentX is where I start my wizard, so I push a new stack like this:
{
// ...
stack: {
children: [
component1,
//...,
componentX,
{
stack: {
children: [step1, step2, /*...,*/ stepN]
}
}
]
}
}
After the user make the last choice on stepN, I would like to replace the nested stack with a summary screen to have something like:
{
//...
stack: {
children: [
component1,
//...,
componentX,
summaryScreen
]
}
}
I could use Navigation.setRoot to reset the whole thing but that means I would probably have to store the navigation in Redux.
I've also tried using Navigation.setStackRoot but I'm under the impression that it's setting the parent stack root and not my nested stack...
I've finally managed to solve it.
Here's how:
At the start of my app, when I give an id to my main stack
const sideMenu = {
left: { /*...*/ },
center: {
stack: {
id: 'main', // this line is important
children: [/*...*/]
}
},
};
Navigation.setRoot({
root: { sideMenu },
});
When I want to start my wizard, I push a new stack
Navigation.push(componentId, {
stack: {
id: 'wizard',
children: [
{
component: { /*...*/ },
},
],
}
})
I push the screens on the new stack wizard as the user progresses
When I want to display the final summary screen, I call setStackRoot on the nested stack
Navigation.setStackRoot('wizard', [
{
component: { /*...*/ },
},
]);
On that summary screen, I have a button labelled 'Finish' which removes the nested stack
Navigation.pop('main');
EDIT: with this approach alone, if you click on the back arrow when you are on a nested screen, it will dismiss the entire nested stack instead of this screen only.
I had to use a custom back button as follows:
I solved it by using a custom back button:
1. When pushing a new screen where I want to override the button, use the options
import Icon from 'react-native-vector-icons/MaterialIcons';
/* ... */
const backIcon = await Icon.getImageSource('arrow-back', 24, '#000');
const component = {
id: screenID,
name: screenID,
passProps,
options: {
topBar: {
leftButtons: [
{
id: 'backButton',
icon: backIcon,
},
],
},
}
};
return Navigation.push(componentId, { component });
Create a HOC to implement you custom back action
import React, { Component } from 'react';
import { Navigation } from 'react-native-navigation';
const getDisplayName = WrappedComponent => WrappedComponent.displayName || WrappedComponent.name || 'Component';
export default function withCustomBackButton(WrappedComponent) {
class WithCustomBackButton extends Component {
componentDidMount() {
this.navigationEventListener = Navigation.events().bindComponent(this);
}
componentWillUnmount() {
if (this.navigationEventListener) this.navigationEventListener.remove();
}
navigationButtonPressed() {
// Your custom action
const { componentId } = this.props;
Navigation.pop(componentId);
}
render() {
return <WrappedComponent {...this.props} />;
}
}
WithCustomBackButton.displayName = `WithCustomBackButton(${getDisplayName(WrappedComponent)})`;
return WithCustomBackButton;
}
When registering the screen with the custom back button, wrap it in your HOC
import withCustomBackButton from '../components/hoc/WithCustomBackButton';
/* ... */
Navigation.registerComponent('selectLocation', () => withCustomBackButton(SelectLocation));

Angular 2: Load data using Server data source into my ng smart table

Has any one figure out on how to load the server data from the ng2-smart table plugin of Angular2.
I have few products data that is retrieved from Node API and Im able to display the same onClick event in the browser log.
I need to display the same in this 3rd party plugins table area which they have provided in this documentation below:
Frontend : https://akveo.github.io/ng2-smart-table/#/examples/populate-from-server
Under "Server Data Source Example"
Code: https://github.com/akveo/ng2-smart-table/blob/master/src/app/pages/examples/server/advanced-example-server.component.ts
Accordingly i have configured in my code as below:
blank-page.component.ts
import { ServerDataSource } from 'ng2-smart-table';
import { Component } from '#angular/core';
import { Http } from '#angular/http';
#Component({
selector: 'advanced-example-server',
template: `
<ng2-smart-table [settings]="settings" [source]="source"></ng2-smart-table>
`,
})
export class BlankPageComponent implements OnInit {
settings = {
columns: {
id: {
title: 'ID',
},
albumId: {
title: 'Album',
},
title: {
title: 'Title',
},
url: {
title: 'Url',
},
},
};
source: ServerDataSource;
//Doubt or Problem here!!!
constructor(http: Http) {
this.source = new ServerDataSource(http, { endPoint: 'https://jsonplaceholder.typicode.com/photos' });
}
//Tried like this too (Which is not the right way of calling)
constructor(http: Http) {
this.source = new ServerDataSource(http, { endPoint: this.productService.getProductsOncategory(this.categoryid) });
}
//Dint work this too!!
constructor(http: Http) {
this.source = new ServerDataSource(http, { endPoint:'http://localhost:5000/products/getProductsOncategory ' });
}
}
Where my service.ts file is like, which actually displays the products data in my browser log which i need to show in my table data
getProductsOncategory(category_id){
let catUrl="http://localhost:5000/products/getProductsOncategory"
let headers = new Headers();
headers.append('Content-Type','application/json');
let catIdObj = JSON.stringify({category_id:category_id})
console.log(catIdObj)
return this.http.post(catUrl,catIdObj,{headers:headers})
.map((response:Response)=>response.json())
.do(data=>console.log(JSON.stringify(data)))
.catch(this.handleError);
}
Error if i use my projects url in endpoint
Error: Uncaught (in promise): Error: Data must be an array. Please check that data extracted from the server response by the key '' exists and is array.
This is what i did and worked perfect for me, i used smart table server side paging, but build my own filter for custom filtration experience.
1- Define Server Data Source
source: ServerDataSource;
2- set it in constructor with config object
this.source = new ServerDataSource(http,
{
endPoint: 'full-url-for-endpoint',
dataKey: 'your-list-path-from-response' for example 'data.records' ,
pagerPageKey: 'your backend param excpected for page number key',
pagerLimitKey: 'your backend param excpected for page size',
totalKey: total records returned in response path for example 'data.total',
filterFieldKey: your filter keys template should set to '#field#' if you need to send params as you set, Default is '#field#_like'
});`
3- add settings object
settings = {
actions: {
custom: [ // if you need custom actions do like that
{ name: 'view-something', title: '<i title="Exception" class="nb-alert"></i>' },
{ name: 'do-custom', title: '<i class="fa fa-pencil"></i>' }
],
add: true, //if you don't need default add button set to false
edit: true, //if you don't need default add button set to false
delete: true, //if you don't need default delete button set to false
position: 'right' // buttons position
}, // remove add , edit , delete objects if you don't use
add: {
addButtonContent: '<i class="nb-plus"></i>',
createButtonContent: '<i class="nb-checkmark"></i>',
cancelButtonContent: '<i class="nb-close"></i>',
},
edit: {
editButtonContent: '<i class="nb-edit"></i>',
saveButtonContent: '<i class="nb-checkmark"></i>',
cancelButtonContent: '<i class="nb-close"></i>',
},
delete: {
deleteButtonContent: '<i class="nb-trash"></i>',
confirmDelete: true,
},
pager: {
display: true // set to false if no need for pagination
},
columns: {
Id: { // set up table cols - Id is a prop name returned from backend
title: 'ID', // display name in table header
type: 'number',
filter: false // add text filter for it or not
},
Name: {
title: 'Full Name',
type: 'string',
filter: false
}
}
};
// Add Filter Data , i used a custom form binded with ngModel above table for filtration, so assume you have a model called filter which get data from external form
FilterData() {
this.source.reset(true); // reset your old filtered data
this.source.setPage(1, false); // set page to 1 to start from beginning
let filterArr = this.getFilterArray(); // add a new filter data, but be careful to not sent any empty data, as it throws an exception
if (filterArr.length)
this.source.setFilter(filterArr, false, false);
this.source.refresh(); // this will call the server with new filter and paginatio data
}
getFilterArray() { // setup new filter
let filterArray = [];
if (this.filter.id)
filterArray.push({ field: 'id', search: this.filter.id });
if (this.filter.name)
filterArray.push({ field: 'name', search: this.filter.name});
return filterArray;
}
onCustomAction(event) { // custom buttons code
switch (event.action) {
case 'view-something':
// put your code here
break;
default:
console.log('Not Implemented Action');
break;
}
}
With this example my data is resource so the datakey is set resource
find below sample code
{
source: ServerDataSource;
constructor(http: HttpClient) {
this.source = new ServerDataSource(http, { dataKey: 'resource', endPoint:'http://localhost:8080/api/v2/mysql/_table/able' })
}
You need to set the dataKey for the ServerDataSource. For example, if your JSON is { data: [...], total: .. }, you need to set dataKey = 'data'.
this worked for me on Angular 8, But Search box functionality needs to be handeled from backend (i.e: localhost:5000/session_info/Seance1?temp_like=30), so backend need to filter (temp_like = value) in database, which make search box retrive live data.
Here is the entire component with Edit and Delete, Enjoy it!
import {Component} from '#angular/core';
import {ServerDataSource} from 'ng2-smart-table';
import {HttpClient} from "#angular/common/http";
import {Setting} from "../../setting";
#Component({
selector: 'ngx-session-man',
templateUrl: './sessions-man.component.html',
styleUrls: ['./sessions-man.component.scss'],
})
export class SessionsManComponent {
settings = {
mode: 'inline',
add: {
addButtonContent: '<i class="nb-plus"></i>',
createButtonContent: '<i class="nb-checkmark"></i>',
cancelButtonContent: '<i class="nb-close"></i>',
},
edit: {
editButtonContent: '<i class="nb-edit"></i>',
saveButtonContent: '<i class="nb-checkmark"></i>',
cancelButtonContent: '<i class="nb-close"></i>',
confirmSave: true,
},
delete: {
deleteButtonContent: '<i class="nb-trash"></i>',
confirmDelete: true,
},
columns: {
name: {
title: 'Séance',
type: 'string',
},
start: {
title: 'Début',
type: 'any',
},
end: {
title: 'Fin',
type: 'any',
},
},
};
source: ServerDataSource;
constructor(private httpClient: HttpClient) {
this.source = new ServerDataSource(this.httpClient, {endPoint: Setting.baseUrl + 'all_sessions_table'});
}
onDeleteConfirm(event): void {
if (window.confirm('Are you sure you want to delete ' + event['data']['name'] + '?')) {
event.confirm.resolve();
this.httpClient.delete<any>('http://localhost:5000/del-seance/' + event['data']['name']).subscribe(
temps => {});
} else {
event.confirm.reject();
}
}
onEditConfirm(event): void {
if (window.confirm('Are you sure you want to edit ' + event['data']['name'] + '\'s name to ' + event['newData']['name'] + '?')) {
event.confirm.resolve();
this.httpClient.post<any>('http://localhost:5000/mod-seance/' + event['data']['name'] + '/' + event['newData']['name'], { title: 'Session deleted' }).subscribe(
temps => {});
} else {
event.confirm.reject();
}
}
}

JayData incorrect behaviour with WebApi v2 Odata during entity Create with kendoGrid

this my Controller:
public class ProductEntityController : EntitySetController<
ProductEntity, int>
{
public IQueryable< ProductEntity> Get(ODataQueryOptions< ProductEntity> parameters)
{
return productList.AsQueryable();
}
public ProductEntity Create(ProductEntity entity)
{
productList.Add(entity);
return entity;
} }
//---------------------------------------
this my JS code:
var context = new $data.initService('/odata');
context.then(function (db) {
var dsD = db.ProductEntity.asKendoDataSource();
grid= $('#gridD').kendoGrid({
dataSource: dsD,
filterable: true,
sortable: true,
pageable: true,
selectable: true,
height: 400,
columns: [
{ field: 'Name' },
{ field: 'Created' },
{ field: 'Index' },
{ field: 'LargeNum' },
{ command: ["edit", "destroy", "update"] }
],
toolbar: ["create", "save", "cancel"],
editable: "inline"
}).data("kendoGrid");
}).fail(function (args) { });
//------
when i "Add New Record" or "Save Changes" , two request are sent to the server(GET and then POST).
i have an error :'result count failed ' at GET Response.
i found a problem in following code in kendo.js:
create: function (options, model) {
var query = self;
query.entityContext.onReady().then(function () {
if (model.length > 1) {
..............
..........
}
else {
console.dir(ctx.storeToken);
model[0]
.innerInstance() // when i comment this line everything is gonna be ok
.save(ctx.storeToken)
.then(function () {
options.success();
})
.fail(function () {
console.log("error in create");
options.error({}, arguments);
});
}
});
}
why is called innerInstance() before save?
how can i fix my problem?
i use Jaydata 1.3.6 with kendo ui and webApi2 Odata on MVC 5
please help me
this problem occurred when i changed default value of key Field(Id) in create mode at Client side. JayData send GET request with filter to the server.therefore i had and error because i didn't have this Id on my entity.then send POST new Entity to the server.
conclusion:don't have permission to edit your key in kendoGrid and handle it at server.

YUI3 Tabview How to determine the label of selected tab

I need a YUI3 tabview like
<div id="demo"></div>
<script>
YUI().use('tabview', function(Y) {
var tabview = new Y.TabView({
children: [{
label: 'foo',
content: '<p>foo content</p>'
}, {
label: 'bar',
content: '<p>bar content</p>'
}, {
label: 'baz',
content: '<p>baz content</p>'
}]
});
tabview.render('#demo');
});
</script>
Now need a event handler which will be of following specification
It will be fired when user will click on tab something like "selectedTabChanged"
Inside the handler will determine the label of the "SelectedTab"
Just add this below tabview.render('#demo');
tabview.on('selectionChange', function (e) {
alert('Changing tab from "' + e.prevVal.get('label') + '" to "' + e.newVal.get('label') + '"');
}

Resources