Meteor: Insert Checkbox (as Boolean) into Sub-Schema (aldeed2) - javascript

I'm trying to insert the checkbox value (as boolean) into a subschema of my collection. Not clear on 1) how to pass the checkbox value (can do it for normal input field) and 2) how to insert into subschema. I am using collection2 and handlebars.
1-This is what I have in the HTML form that needs to be submitted:
`<div class="checkbox">
<label><input type="checkbox" id="byow" checked="{{isChecked}}" value="">Bring Your Own Wine</label></div>`
2-This is what I have in my helper (in controller) to get the value of the form and the checkbox value, submit it and call the method that inserts it into the collection:
`BackendController.events({
//Add Venue - Add New Venue Submit Form Helper
'submit #add-venue-form' : function(event) {
event.preventDefault();
var venueName = event.target.venueName.value;
var byow = event.target.byow.checked;
var params = {
venueName: venueName,
byow: byow
}
//Insert Venue
Meteor.call('addVenue', params);
toastr.success('VenueAdded');
Router.go('/admin/manage-venues')
}
3-This is my method that is called to insert into my Venues collection (first part) and the structure of my collection and sub-collection:
`Meteor.methods({
'addVenue': function (params) {
Venues.insert(params);
}
// MAIN SCHEMA for the Venues colleciton.
Schema.Venues = new SimpleSchema({
venueName: {
type: String,
label: "Venue Name",
max: 200,
optional: false
},
//Attach schema for venue attributes (cuisine type, amenities, etc)
venueAttributes: {
type: Schema.VenueAttributes,
optional: true
}
});
//schema for venue attributes. Attached to main schema
Schema.VenueAttributes = new SimpleSchema({
byow: {
type: Boolean,
optional: true
}
});
Would really appreciate any help - I've managed to get the venueName to be passed successfully (so all my permissions/pub/sub is correct) but stuck at checkbox and subcollection.
Thanks!
Dan.

Finally figured it out with the help of #lokenx on Meteor Chef Slack channel.
The checkbox code (first part) returned the correct value (true) when written as above.
My error was that I was not specifying byow as a subproperty (was treating it as root property of the simpleschema). The correct params I should have been passing are:
var params = {
venuaName: venueName,
venueAttributes: {
byow: byow
}
}

Related

NetSuite is entirely new to me and I'm trying to create a suitelet that needs to reflect my active roles. How shall I execute it in codes?

I know that there already is a 'View My Roles' under my account but I just need that page to reflect on a suitelet.
You will want to use the Suitelet Script Type, and methods available in the N/runtime Module (to get current user and role) and N/ui/serverWidget Module (to create the custom page). You can use methods in either the N/record Module or N/search Module (to gather user role data).
Here's a good start to how to outline your script. Once deployed as a Suitelet you will see a url provided. This will be the url to use to trigger the script. I do not know of a way to make the link attached to a Custom Center Tab, but minimally you can have users save the link to their NetSuite shortcuts, or browser shortcuts.
/**
* #NApiVersion 2.x
* #NScriptType Suitelet
*/
define(['N/ui/serverWidget', 'N/runtime', 'N/record'], function(serverWidget, runtime, record) {
function onRequest(context){
if(context.request.method === 'GET'){ //GET is the request method when clicking on the url, POST or ELSE logic can be entered if you want to add for example a "submit button"
//create list w/2 columnms to display results in
var list = serverWidget.createList({
title: 'Available User Roles'
});
list.style = serverWidget.ListStyle.REPORT;
list.addColumn({
id: 'column1',
type: serverWidget.FieldType.TEXT,
label: 'Active Role?',
align: serverWidget.LayoutJustification.LEFT
});
list.addColumn({
id: 'column2',
type: serverWidget.FieldType.TEXT,
label: 'Role Name',
align: serverWidget.LayoutJustification.LEFT
});
//get current user role
var curUser = runtime.getCurrentUser(); //returns User (likely Employee) internal id
var curUserRoleId = curUserRole.role; //returns current role internal id
//empty array to keep all available roles
var availRoles = new Array();
//get all available roles using search or record module
//push each result to the array
availRoles.push(XXX);
//use ids to identify which result found above is the current role
var curRolePosition = availRoles.indexOf(curUserRoleId);
//add data to the list using addRow or addRows
//can also use a for loop for each result found when getting all available roles using search or record module
list.addRow({
row : { columnid1 : 'value1', columnid2 : 'value2' }
});
list.addRows({
rows : [{columnid1 : 'value1', columnid2 : 'value2'},
{columnid1 : 'value2', columnid2 : 'value3'}]
});
//display list to the user
context.response.writePage(list);
} else { //code that is exectuted i.e. after user presses "Submit button" (if created above in the GET area)
}
}
return {
onRequest: onRequest
}
});

How can ajax based Select2 pre-population be formatted?

We've found several examples of pre-populating selected option for Select2, however none of them we could find deal with formatted list and selection options. We have a JS fiddle at https://jsfiddle.net/gpsx62de/26/ that illustrates the issue. In that fiddle, you can type and L or whatever into the select search and the data is returned, the list is formatted, and if you select something, the selection is formatted.
However if you click the button in that JS Fiddle which is intended to simulate pre-population per https://select2.org/programmatic-control/add-select-clear-items#preselecting-options-in-an-remotely-sourced-ajax-select2 the data is returned (you can uncomment the console.log to see it), but the formatted selection shows undefined for the intended values. Does anyone know of a way to get the formatted values for pre-populated data to display correctly?
// Set up the Select2 control
$('#mySelect2').select2({
ajax: {
url: '/api/students'
}
});
// Fetch the preselected item, and add to the control
var studentSelect = $('#mySelect2');
$.ajax({
type: 'GET',
url: '/api/students/s/' + studentId
}).then(function (data) {
// create the option and append to Select2
var option = new Option(data.full_name, data.id, true, true); //**** DOES IT MATTER WHAT IS PASSED HERE BECAUSE WE ARE NOT DISPLAY THE OPTION TEXT?? ***
studentSelect.append(option).trigger('change');
// manually trigger the `select2:select` event
studentSelect.trigger({
type: 'select2:select',
params: {
data: data //**** THIS DOES NOT SEEM TO SUPPORT FORMATTED SELECTIONS, SO HOW CAN THIS BE DONE? ***
}
});
});
The problem is in format_selection function. The format of the object it receives depends on how it was created. When you use new Option(text, value) it receives only the properties of this Option object, not your original object containing all user info.
A workaround is to check of either possible values in the fuction:
function format_selection(obj) {
let name = obj.name || obj.element.text;
let email = obj.email || obj.element.email;
return $(`<div><b>${name}</b></div><div>(${email})</div>`);
}
For this to work you should append the de property on you Option object:
var option = new Option(data.name, data.id, true, true);
option.email = data.email;
$('#sel').append(option).trigger('change');
The problem, in https://jsfiddle.net/gpsx62de/26/ is with the
function format_selection(obj) {
// Just add this to see the obj
console.log(obj);
return $(`<div><b>${obj.text}</b></div><div>(${obj.id})</div>`);
}
The obj object just contains the Option class data, so:
id: "1",
selected: true,
text: "Leanne Graham",
title: ""
So you have to find a way to pass "data.email" to the "format_selection" method
EDIT
This could be a solution
$('#btn').on('click', function() {
$.ajax({
type: 'GET',
url: 'https://jsonplaceholder.typicode.com/users/1'
})
.then(function(data) {
console.log(data)
// create the option and append to Select2
$('#sel').append($('<option />') // Create new <option> element
.val(data.id) // Set value
.text(data.name) // Set textContent
.prop('selected', true)
.attr('data-name', data.name) // Don't know why the .data(key, value) isn't working...
.attr('data-email', data.email))
.trigger('change');
}); //then
}); //click
And
function format_selection(obj) {
return $(`<div><b>${obj.element.dataset.name}</b></div><div>(${obj.element.dataset.email})</div>`);
}
This is the fiddle https://jsfiddle.net/947jngtu/

Save the current user value to use it in HTML

[EDIT] i'm using Meteor
Hi everyone,
i've searched and tried many things but i can't do what i want.
I'm doing a tutorial to do a ToDo list, and when u check a task, i want to put the name of the user who checked the task.
<template name="task">
<li class="{{#if checked}}checked{{/if}}">{{#if checked}}<!-- the name of the user who checked it -->{{/if}}
<!-- the rest isn't useful for my question -->
I've tried with {{currentUser.username}} but when i log with someone else the name change...
There is the JS for the event handler
'click .toggle-checked'() {
// Set the checked property to the opposite of its current value
Meteor.call('tasks.setChecked', this._id, !this.checked);
}
And the JS for the method call
'tasks.setChecked'(taskId, setChecked) {
check(taskId, String);
check(setChecked, Boolean);
Tasks.update(taskId, { $set: { checked: setChecked } });
}
Thank you for the help
If you use {{currentUser.username}} you will always have the data of the logged in user.
To get what you want you need to register the _id of the user who checked the task in your method:
'tasks.setChecked'(taskId, setChecked) {
check(taskId, String);
check(setChecked, Boolean);
// Check that 'setChecked' is true and that the user is logged in,
// Otherwise just update the status
if (setChecked && this.userId) {
Tasks.update(taskId, {
$set: {
checked: setChecked,
userId: this.userId,
}
});
} else {
Tasks.update(taskId, {
$set: {
checked: setChecked,
}
});
}
}
Make sure you update your schema accordingly if you are using one.
Then in your template, retrieve the user data and display it:
// file task.js
import './task.html';
Template.task.helpers({
checkerUser() {
// The template data are those of the current task, check if userId is defined and task is checked
const { userId, checked } = Template.currentData();
/* Or you can do
* const userId = Template.currentData().userId;
* checked = Template.currentData().checked;
*/
if (userId && checked) {
return Meteor.users.findOne({ _id: userId }).profile.username;
}
return null;
}
});
Template.task.events({
'click .toggle-checked'() {
// Set the checked property to the opposite of its current value
Meteor.call('tasks.setChecked', this._id, !this.checked);
}
})
And finally in HTML:
// file task.html
<template name="task">
<li class="{{#if checked}}checked{{/if}}">
{{#if checkerUser}}Completed by {{checkerUser}}{{/if}}
</li>
</template>
Technically, in your method you should also check more in-dept the different situations. For instance, when you uncheck a task, it should remove the userId from the record so that if a non logged-in user checks it again, the name won't be the one of the first user (or you could $unset userId if user is not logged in when setting checked = true)

Passing nested knockout view model to controller

This is fleet management app in mvc EF and knockout , there are VEHICLES , DRIVERS and specific ROUTES that the drivers travel.
I have a situation where I would like to gather field values from three models nested within my view models into a single object and post it my backend via ajax. I want this to be triggered by clicking a button.
There is a problem is in my populateFleetInformation function. When I gather the field values from my various models, some of the observables are losing their values and appear as null.
The view model that attempts to make the ajax call
function FleetViewModel() {
var vvm = this;
vvm.regNumber = ko.observable(0);
vvm.make = ko.observable("");
vvm.model = ko.observable("");
vvm.RouteDetail = new RouteViewModel();
vvm.SaveFleetInfo = function(item){
if (!pageViewModel.isAuthenticated()) return;
populateFleetInformation(item);
$.when(postSecureData("/api/Fleet/", ko.toJSON(pageViewModel.FleetViewModel.RouteViewModel.RouteDriverViewModel)))
.done(function () {
document.getElementById("save-Fleet-btn").innerHTML = "Saving...";
setTimeout(function () { document.getElementById("save-fleet-btn").innerHTML = "Save" }, 2500);
$.msgGrowl({
type: 'info',
title: 'Fleet Information',
text: 'fleet information succesfully saved',
position: 'bottom-right',
lifetime: 3000
});
})
}
}
function that gathers data
function PopulateFleetInformation(item)
{
pageViewModel.fleetVM.regNumber(item.regNumber);
pageViewModel.fleetVM.make(item.make);
pageViewModel.fleetVM.model.(item.model);
pageViewModel.fleetVM.routeDetail.routeID(item.routeId);
pageViewModel.fleetVM.routeDetail.routeName(item.routeName);
pageViewModel.fleetVM.routeDriver.nationalId(item.nationalId);
pageViewModel.fleetVM.individualMsisdn.licenseId(item.licenseId);
pageViewModel.fleetVM.individualMsisdn.driverName(item.driverName);
}
The trigger button
<button type="submit" id="save-fleet-btn" class="btn"data-bind="click: $root.fleetVM.sensorDetail.SaveFleetInfo"></button>
This function:
function PopulateFleetInformation(item)
{
pageViewModel.fleetVM.regNumber(item.regNumber);
pageViewModel.fleetVM.make(item.make);
pageViewModel.fleetVM.model.(item.model);
pageViewModel.fleetVM.routeDetail.routeID(item.routeId);
pageViewModel.fleetVM.routeDetail.routeName(item.routeName);
pageViewModel.fleetVM.routeDriver.nationalId(item.nationalId);
pageViewModel.fleetVM.individualMsisdn.licenseId(item.licenseId);
pageViewModel.fleetVM.individualMsisdn.driverName(item.driverName);
}
is not doing what you think it is at all.
itemis coming from the context passed into SaveFleetInfo by knockout when your button is clicked. This function is then setting the values of the fields you are trying to retrieve to whatever is in item; I'm guessing you're getting all sorts of undefined exceptions here.
What you want to do is this:
function PopulateFleetInformation()
{
return {
regNumber: pageViewModel.fleetVM.regNumber();
make: pageViewModel.fleetVM.make();
model: pageViewModel.fleetVM.model.();
routeId: pageViewModel.fleetVM.routeDetail.routeID();
routeName: pageViewModel.fleetVM.routeDetail.routeName();
nationalId: pageViewModel.fleetVM.routeDriver.nationalId();
licenseId: pageViewModel.fleetVM.individualMsisdn.licenseId();
driverName: pageViewModel.fleetVM.individualMsisdn.driverName();
}
}
This function returns the values you are after as an object, then you can post this data like this:
var data = populateFleetInformation();
$.when(postSecureData("/api/Fleet/", ko.toJSON(data)))

Kendo template send data

What I want is simple but I don't know if it's possible.
I have a Kendo Mobile ListView as below:
e.view.element.find("#list-serviceorders").kendoMobileListView({
dataSource: ds,
pullToRefresh: true,
template: $("#list-serviceorders-template").html()
});
And I want to send to the template some values to access on it. My view with the template is this:
<div data-role="view" data-before-show="GAPCP.viewBeforeShow" id="serviceorders" data-layout="main-item-list">
<ul id="list-serviceorders"></ul>
</div>
<script id="list-serviceorders-template" type="text/x-kendo-template" data-teste="teste">
<a href="views/entries.html?id=#: CodOs #">OS: #: CodOs #<br />
#: parameter.Divi1 #: #: CodDivi1 #/#: parameter.Divi2 #: #: CodDivi2 #</a>
</script>
Where you can read parameter.Divi1 and parameter.Divi2 are the places where I want to display those values. They're are not in the Data Source like the others values.
I don't want to create global variable 'cause I don't want to mess with my code and I can't use a function for that purpose because those values come from the database and it will execute a query for each list item iteration.
Any suggestion of how do that?
What I'm proposing is adding this information to the model in the controller. You can do it in DataSource.schema.parse or in requestEnd, even in a dataBound event if the widget accepts it.
When the data is received you iterate through the model and fills the remaining data not received from the server.
Example: Using parse
var ds = new kendo.data.DataSource({
transport: {
read: {
url : ...
}
},
schema : {
model: {
CodOs : { type: "number" },
CodDivi1: { type: "string" },
CodDivi2: { type: "string" }
},
parse: function (data) {
$.each(data, function (idx, elem) {
// Extend original elem
elem.parameter = {
Divi1: elem.CodDivi1.toUpperCase(),
Divi2: elem.CodDivi2.toLowerCase()
}
});
return data;
}
}
});
Where I compute parameter inside the parse function and set parameter.Divi1 to CodDivi1 in upper-case and parameter.Divi2 to CodDivi2 in lowercase.

Categories