How can we save data from AUI DataTable Text Area Cell Editor to server.
I am doing something like:
var nameEditor = new Y.TextAreaCellEditor({
validator : {
rules: {
name:{
email:true,
required:true,
}
}
}
});
How can I get a handler to send a request to server in order to save data from that editor column
The base editor registers a save event to which you would want to listen.
To register the subscription:
nameEditor.on('save', function(e){
var msg = 'Details : newVal=' + e.newVal
+ ' oldVal=' + e.prevVal;
alert(msg)
});
Fiddle
Related
I have a partner record where I would like to change the form if the category field is set to a certain value. However, I can't use this with certain SuiteScript functions because changing the form wipes out any changes that were made to the record. I'm trying to work around this using an afterSubmit function that will use record.SubmitFields to change the form and then redirect.toRecord to reload the page with the change. However, it's not changing the form value. Is there a way to do this with record.submitFields? Am I doing something incorrectly?
var currentRecord = scriptContext.newRecord;
var category = currentRecord.getValue('category');
if(category == '3'){
try{
record.submitFields({
type: record.Type.PARTNER,
id: currentRecord.id,
values: {
'customform': '105'
}
});
log.debug('success');
} catch (e) {
log.error({title: 'error', details: e});
}
}
redirect.toRecord({
type: 'partner',
id: currentRecord.id,
});
}
Yes you can. Whenever you create a url for a record you can generally add a cf parameter that takes the form id. It's the same vaule you'd use if you were setting the field 'customform'. So just skip the submitFields part and do:
redirect.toRecord({
type: 'partner',
id: currentRecord.id,
parameters:{
cf:105
}
});
You can also set the custom form using the submitFields call but that only works for some types of records.
If you need to do this in the beforeLoad here is a fragment in Typescript. The trick to avoid an infinite loop is to check to see if you already have the correct form:
export function beforeLoad(ctx){
let rec : record.Record = ctx.newRecord;
let user = runtime.getCurrentUser();
if(user.roleCenter =='EMPLOYEE'){
if(rec.getValue({fieldId:'assigned'}) != user.id){
throw new Error('You do not have access to this record');
return;
}
}else{
log.debug({
title:'Access for '+ user.entityid,
details:user.roleCenter
});
}
if(ctx.type == ctx.UserEventType.EDIT){
var approvalForm = runtime.getCurrentScript().getParameter({name:'custscript_kotn_approval_form'});
let rec : record.Record = ctx.newRecord;
if( 3 == rec.getValue({fieldId:'custevent_kotn_approval_status'})){
if(approvalForm != rec.getValue({fieldId:'customform'}) && approvalForm != ctx.request.parameters.cf){
redirect.toRecord({
type: <string>rec.type,
id : ''+rec.id,
isEditMode:true,
parameters :{
cf:approvalForm
}
});
return;
}
}
}
I have created a saved search for transaction in netsuite and with suitescript 2.0 I am showing saved search data in my application. In application user can apply filter on any fields (please see the attached screenshot). For example user select "Aug 2011" for posting period, only transactions of Aug 2011 should be loaded. This works fine if I create a filter with internalid of "Aug 2011", but on UI I dont have internal id.
sample code:
/*
here is my required module
*/
function getTransactionData(datain)
{
try
{
var objSearch = search.load
({
id: datain.savedsearchid
});
/***** Work *****/
objSearch.filters.push(search.createFilter({ name: "postingperiod", operator: "ANYOF", values: "1" })); //here 1 is internalid of periodname "Aug 2011"
/***** Not Work (SSS_INVALID_SRCH_FILTER_JOIN) *****/
//objSearch.filters.push(search.createFilter({ name: "postingperiod", join: "accountingperiod", operator: "ANYOF", values: "Aug 2011" }));
objSearch.run();
}
catch(ex)
{
log.error("getTransactionData", ex);
throw ex;
}
}
I tried with join but seeing "SSS_INVALID_SRCH_FILTER_JOIN" error from Netsuite.
Can any one please help me regarding this.
Thanks in advance
I edited your code to a more simplified one to understand better.
If you get the gist of how it works, you can edit/customize the way you want.
I assume there is join 'accountingperiod' option available for 'postingperiod' and this works perfectly in your saved search you created in netsuite without using suitescript.
/*
here is my required module
*/
function getTransactionData(datain) {
try {
var objSearch = search.load({
id: datain.savedsearchid
});
var defaultFilters = objSearch.filters;
var customFilters = [];
//Adding filter
customFilters = ['postingperiod', 'ANYOF', '1'];
defaultFilters.push(customFilters);
customFilters = undefined;
customFilters = [];
//Adding filter
/*
customFilters = ['postingperiod.accountingperiod', 'ANYOF', 'Aug 2011'];
defaultFilters.push(customFilters);
*/
objSearch.filters = defaultFilters;
var objSearch_run = objSearch.run().getRange({
start: 0,
end: 10
});
} catch (ex) {
log.error("getTransactionData", ex);
throw ex;
}
}
If you want to know how filters is stored in saved search you created in netsuite, you can use the script debugger.
The following code is suitescript 1.0
//Load Saved Search
get();
function get() {
var search = nlapiLoadSearch('transaction', ' ENTER SAVED SEARCH ID HERE ');
log.debug('search',search);
var searchFilters = search.getFilterExpression();
log.debug('searchFilters',searchFilters);
return search;
}
I assume your application is a Suitelet? If so, you need to do a select field type of your record. So probably of 'posting periods'. This will show your periods in a drop down.
When the user selects it, have a client side script auto refresh the data and load your saved search.
Alternatively, you can load all the data and do the filtering client side DOM filtering. Really need a bit more information about your "application".
This is a document from my todo mongodb:
"_id" : ObjectId("5a1e96f856f24c43b886eb54"),
"title" : "Drink coffee",
"note" : "Tomorrow morning",
"open" : true,
"duedate" : "2017-12-03"
This is the pug code that populates a todo list page
each todo in todolist
if todo.open
div
a(href="#") #{todo.title}
div
p(style='white-space:pre;')
| #{todo.note}
| Due: #{todo.duedate}
button(id="doneButton") Done
The above works fine. The todo page displays all todo items as expected.
What I want to do:
When user clicks on 'Done' button, I want to update that particular document to "open": false.
(I want to do this onclick, and not by loading the item on a new edit page with an edit button. When todo list page reloads, that todo item is removed from the list. I do not want to delete the document as I need to archive it later on.)
So my questions are:
How do I code the 'Done' button on the pug page so that it gets
associated with the particular document that needs to be updated?
How do I structure the POST code on my index.js so that it listens for
the button click and performs the relevant document update?
UPDATE
OK, so I don't know enough to understand kentor's reply (but thank you anyway!). I did a bit of research though and some copying and pasting, and I have moved the problem a couple of steps forward - I hope.
New pug code:
each todo in todolist
if todo.open
a(href="#") #{todo.title}
p #{todo.note}
p Due: #{todo.duedate}
form#form_update_item(name="updateitem", method='post', action='/updateitem')
input#input_name(type="hidden", placeholder="", name="_id", value="#{todo._id}")
button(type="submit") Done
index.js code
router.post('/updateitem', function(req, res) {
var MongoClient = mongodb.MongoClient;
var ObjectId = require('mongodb').ObjectId;
var url = 'mongodb://localhost:27017/tododb';
MongoClient.connect(url, function(err, db) {
if (err) {
console.log("can't connect", err);
}
else {
console.log('Connected to server. Woohoo!');
var collection = db.collection('todolist');
collection.findOneAndUpdate(
{"title": "Make smoothie"},
{
$set: {
"open": false
}
},
function(err, result) {
if (err) {
console.log(err);
} else {
res.redirect("todolist");
}
db.close();
});
}
});
});
What happens now:
On button click, doc with title "Make Smoothie" changes to "open": false. So button triggers the change I want. Bang! But this is only a partial solution to help me isolate the problem.
What I still need:
On button click, I want the doc's ID whose button was clicked to replace {"title": "Make smoothie"} so that the "open": false change can be made. Something like {_id: "doc ID coming from button blah blah"}.
UPDATE 2
Discovered that I was using Jade syntax not Pug, so instead of this
value="#{todo._id}
I should be using
value=todo._id
So now index.js can console.log the ID the Pug form is passing. Last challenge is to use that ID to change the corresponding mongodb document as described above.
I finally solved it
Last step, I replaced
{"title": "Make smoothie"}
with
{"_id": ObjectId(req.body._id)}
and sure enough, every time I click on a button, the server updates the corresponding document's "open": false
You could just attach a data attribute to the HTML button like this:
button(id="doneButton", data-id=todo._id) Done
Then you would just attach an event listener to this button and send a POST request containing this data-id. Using Jquery it could look like this:
.script
$('#doneButton').on("click", function (element) {
var data = $(this).data("id");
$.ajax({
type: "POST",
url: "your-url",
data: { todoId: data },
success: responseHandler
})
})
Regarding these post : Mongoose prototype : how to insert an url dynamically?
I'm looking to do pretty much the same (URI dynamically insert).
The solution provided is good but I do not understand some things...
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var PicturesSchema = new Schema({
album : { type : String, required : true, trim : true },
pictures : { type : Array, required : false, trim : true }
});
PicturesSchema.virtual('pictureUrls').get(function() {
return this.pictures.map(function(picture) {
return 'https://s3.amazonaws.com/xxxxx/'+ picture;
});
});
var Pictures = mongoose.model('Pictures', PicturesSchema);
// Demo:
var pictures = new Pictures({
album : 'album1',
pictures : [
'1434536659272.jpg',
'1434536656464.jpg',
'1434535467767.jpg'
]
});
console.log( pictures.getPics() );
The given solution injects a "virtual field" in addition to retaining the "pictures" field with the name of the images (without URL).
How to retain only the field "PicturesURL" containing the full URL of the image without displaying a redundancy with the "Pictures" field?
How to retrieve and display the JSON format query results as it knowing that data.ToJson returns an error: has no method 'toJson'?
Pictures.find().exec(function(err, data){
if(err){
console.log(err);
}
console.log('%j', data.toJSON({ virtuals : true }) );
});
A strategy to store only the picture url without the picture would be to create a Mongoose middleware on save.
You could then populate the picture field with the name of the picture, and the full url will be the one stored in the database and later retrieved.
For example:
PictureSchema.pre('save', function (next){
if (this.isModified(pictureUrls){
this.pictureUrls = this.pictureUrls.map(function(picture){
return 'https://s3.amazonaws.com/xxxxx/'+ picture;
})
}
});
With this solution, every time you modify the pictures array, it will go over every element of the array and add the s3 path.
Since it won't be a virtual, it will be easier for you to use the model with event using toObject or toJson.
I'm writing a code , so that I can change column's editor manually . I'm able to set editor event on double click event ('dblClick') .
When I click on cell, effect is observe on next click .
What is missing ?
Or
How can open/show editor manually ?
My code is like .......
table.delegate('dblclick', function(e) {
var target = e.currentTarget;
var model = table.getRecord(target.get('id'));
var type = model.get('type');
var column = this.get('columns.value');
column.editor = editors[type];
this.showCellEditor(target);
},'tr', table);
this.showCellEditor(target); --> this method is of YUI (Yahoo's UI) . Is any method is resemble to this one in Alloy UI ?
Instead of selecting an editor on the fly, why not group similar data in the same column so that the same editor can be used?
var columns = [{
editor: new Y.TextAreaCellEditor(),
key: 'name'
}, {
editor: new Y.DateCellEditor({
dateFormat: '%m/%d/%Y'
}),
key: 'birthday'
}];
If you group the data like that, then you can change the editEvent of the dataTable to dblclick like so:
var dataTable = new Y.DataTable({
// ...
editEvent: 'dblclick'
}).render('#dataTable');
Here is a working example:
YUI().use('aui-datatable', function(Y) {
var columns = [{
editor: new Y.TextAreaCellEditor(),
key: 'name'
}, {
editor: new Y.DateCellEditor({
dateFormat: '%m/%d/%Y'
}),
key: 'birthday'
}];
var data = [{
birthday: '9/9/1999',
name: 'Jonathan Smithy'
}, {
birthday: '10/10/1990',
name: 'Bob Duncan'
}];
var dataTable = new Y.DataTable({
columnset: columns,
recordset: data,
editEvent: 'dblclick'
}).render('#dataTable');
});
<script src="https://cdn.rawgit.com/stiemannkj1/701826667a70997013605edcd37e92a6/raw/469fe1ae297e72a5a80eb9015003b7b04eac735e/alloy-ui-3.0.1_aui_aui-min.js"></script>
<link href="https://cdn.rawgit.com/stiemannkj1/90be22de7f48c729b443af14796d91d3/raw/a9f35ceedfac7fc0559b121bed105eaf80f10bf2/aui-css_css_bootstrap.min.css" rel="stylesheet"></link>
<div id="dataTable"></div>
If you must dynamically choose and display the editor, I'd recommend taking a look a the getEditor(record, column) method of A.DataTable.CellEditorSupport. I was unable to get getEditor() to work, but I'd assume that if you can get it working, you could do something like getEditor(data[1], column[0]).show().