Given this fiddle, how can I properly populate searchResult with dummyResults and visibleItem with dummyItems?
http://jsfiddle.net/scottbeeson/SRUKN/
var dummyResults = [
{ name: "Server1", type: "Server" },
{ name: "Server2", type: "Server" },
{ name: "Server3", type: "Server" },
{ name: "App1", type: "Application" },
{ name: "App2", type: "Application" },
{ name: "App3", type: "Application" }
]
var dummyItems = [
{ name: "Server1", type: "Server" }
]
function visibleItem() {
var self = this;
this.name = ko.observable("");
this.type = ko.observable("");
this.description = ko.observable("");
}
function searchResult() {
var self = this;
this.name = ko.observable("");
this.type = ko.observable("");
}
var viewModel = {
searchResult: searchResult(),
visibleItem: visibleItem(),
showItem: function (item) {
visibleItems.push(item);
}
}
$(document).function() {
ko.mapping.fromJS(dummyResults, searchResult);
ko.mapping.fromJS(dummyItems, visibleItem);
ko.applyBindings(viewModel);
tmp = ko.toJS(viewModel);
}
Here's a working edit of your fiddle with simplified html.
var viewModel = {
searchResult: ko.observableArray(ko.utils.arrayMap(dummyResults, function (item) {
return new SearchResult(item);
})),
visibleItem: ko.observableArray(ko.utils.arrayMap(dummyItems, function (item) {
return new VisibleItem(item);
})),
showItem: function (item) {
visibleItems.push(item);
}
};
Related
Here's my Mongoose model schema:
MyBox = new Schema(
{
id: { type: Schema.Types.ObjectId },
name: { type: Schema.Types.String},
value: { type: Schema.Types.Number},
};
MyCar = new Schema(
{
id: { type: Schema.Types.Map,ObjectId },
box: { type: Schema.Types.Map, of: MyBox}
};
Data example
{ "_id" : 1,
"box" : {
"box_for_angel": { name: "apple", price:100 },
"box_for_peter": { name: "banana", price:120 }
}
}
how could I get the name of box map?
like ["apple", "banana"]
I have a field achivment with an array of objects. I need to update the field currentPoints in one object that I will find by field name in the array.
Code model of mongoose:
const achive = new Schema(
{
achiveId: ObjectId,
name: { type: String, required: true },
finishedPoints: { type: Number, required: true },
currentPoints: {
type: Number,
default: 0,
set: function (v) {
if (v >= this.finishedPoints) this.isFinished = true;
return v;
}
},
isFinished: { type: Boolean, default: false }
},
{ _id: false }
);
const achivesSchema = new Schema({
userId: ObjectId,
achivement: [achive]
});
Code query:
export async function progressAchive(req, res) {
const value = 3;
try {
const test = await Achives.updateOne(
{
userId: req.user._id,
achivement: { $elemMatch: { name: req.params.nameAchive } }
},
{ $set: { achivement: { currentPoints: value } } },
{ new: true }
);
res.json(test);
} catch (e) {
console.log(e);
}
}
Instead of updating, it removes all objects from the array and leaves them one object with the currentPoint field. How can I update this like I want?
You should use the following for update
const test = await Achives.updateOne(
{
userId: req.user._id,
},
{
$set:{"achivement.$[el].currentPoints": value}
},
{
arrayFilters:[{
"el.name": req.params.nameAchive
}],
new: true
}
);
I am using collection2 with meteor to set default values. However when i run the method Meteor.call('commands.insert', {}) on the client, it just sets new document's ID, and only when the result from server comes it replaces the document with the right value. Actually, autoValue function runs on client because when i console.log there it logs (also tried defaultValue), but it does not do anything, does no modifications, nor unique: true is working, any property specified in the schema
server
export const Commands = new Mongo.Collection('commands')
Commands.schema = new SimpleSchema({
designation: {
type: String,
autoValue: function() {
console.log("inssssssssssssssssssseeeeeeeeeeeeeeeeeeeeeeert")
if (this.isInsert) {
return "Untitled"
}
},
unique: true
},
name: {
type: String,
autoValue: function() {
if (this.isInsert) {
return ""
}
},
optional: true
},
syntax: {
type: String,
autoValue: function() {
if (this.isInsert) {
return ""
}
},
optional: true
},
description: {
type: String,
autoValue: function() {
if (this.isInsert) {
return ""
}
},
optional: true
},
features: {
type: String,
autoValue: function() {
if (this.isInsert) {
return ""
}
},
optional: true},
type: {
type: String,
autoValue: function() {
if (this.isInsert) {
return ""
}
},
optional: true
},
variants: {
type: Array,
autoValue: function() {
if (this.isInsert) {
return []
}
},
},
'variants.$': {type: String}
})
Commands.attachSchema(Commands.schema)
Meteor.methods({
'commands.insert'(command) {
if (!this.userId) {
throw new Meteor.Error('not-authorized')
}
Commands.insert(command)
}
})
client
const setNewHandler = this.props.page.animationFinished ?
this.props.page.editing ?
textEditorData.length ?
() => {
Meteor.call(
'commands.update',
textEditorData[0]._id,
{
designation:
this.childComponents[0].editableContentNode.textContent,
name:
this.childComponents[1].editableContentNode.textContent,
syntax:
this.childComponents[2].editableContentNode.textContent,
type:
this.childComponents[3].editableContentNode.textContent,
variants:
this.childComponents[4].editableContentNode.textContent.split("\n"),
description:
this.childComponents[5].editableContentNode.textContent,
features:
this.childComponents[6].editableContentNode.textContent
}
)
} :
null :
() => {
Meteor.call('commands.insert', {})
} :
null
I want to customize the dialog box in jqx scheduler dialog box title. Instead of 'Create new appointment' i want to display "Create a new business schedule".
I work with python django so in the code there are some elements from django template code. So far i create , edit, delete appointments with ajax and django as backend.
var items;
function setAvailability(price_data,persons_data,start_date,end_date, id, a_type, description){
availability_data = {
pk : "{{form.instance.pk}}",
csrfmiddlewaretoken: "{{ csrf_token }}",
price:price_data,
persons:persons_data,
from_date:start_date,
to_date:end_date,
a_type_data:a_type,
av_description:description
}
if(id) {
availability_data['event'] = id;
}
$.ajax({
url: "{% url 'set-availability' %}",
method: "POST",
data: availability_data,
dataType: "json",
success: function(response){
var source = {
datatype: "json",
dataFields: [
{ name: 'id', type: 'integer' },
{ name: 'description', type: 'string' },
{ name: 'location', type: 'string' },
{ name: 'status', type: 'string' },
{ name: 'price', type: 'number' },
{ name: 'persons', type: 'number' },
{ name: 'subject', type: 'integer' },
{ name: 'start', type: 'date', format: "yyyy-MM-dd"},
{ name: 'end', type: 'date', format: "yyyy-MM-dd"}
],
id: 'id',
url: "{% url 'get-availability' %}?pk={{form.instance.pk}}"
};
var adapter = new $.jqx.dataAdapter(source);
$("#scheduler").jqxScheduler({
source: adapter
})
return response;
}
})
}
$.ajax({
url: "{% url 'get-availability' %}",
method: "GET",
data: { pk : "{{form.instance.pk}}" },
dataType: "json",
success: function(response){
items = response;
var source = {
datatype: "array",
dataFields: [
{ name: 'id', type: 'integer' },
{ name: 'description', type: 'string' },
{ name: 'location', type: 'string' },
{ name: 'status', type: 'string' },
{ name: 'price', type: 'number' },
{ name: 'persons', type: 'number' },
{ name: 'subject', type: 'integer' },
{ name: 'start', type: 'date', format: "yyyy-MM-dd"},
{ name: 'end', type: 'date', format: "yyyy-MM-dd"}
],
id: 'id',
localData: items
};
var adapter = new $.jqx.dataAdapter(source);
$("#scheduler").jqxScheduler({
date: new $.jqx.date(2018, 02, 01),
width: 850,
height: 600,
source: adapter,
editDialogDateTimeFormatString: 'yyyy-MM-dd',
editDialogDateFormatString: 'yyyy-MM-dd',
showLegend: false,
localization: { editDialogStatuses: {
available: "Available",
booked: "Booked"
}},
renderAppointment: function(data)
{
if (data.appointment.status == "available") {
data.style = "#B8E6A3";
}
else if (data.appointment.status == "booked") {
data.style = "#FF0013";
}
return data;
},
ready: function () {
$("#scheduler").jqxScheduler('ensureAppointmentVisible', 'id1');
},
resources:
{
colorScheme: "scheme05",
dataField: "id",
source: new $.jqx.dataAdapter(source)
},
appointmentDataFields:
{
id: "id",
description: "description",
location: "location",
subject: "subject",
price: "price",
persons: "persons",
status: "status",
calendar: 'calendar',
from: "start",
to: "end",
},
view: 'monthView',
views:
[
'monthView'
],
renderAppointment: function (dialog, fields, renderAppointment) {
console.info('render appointment:', dialog);
},
editDialogCreate: function (dialog, fields, editAppointment) {
fields.repeatContainer.hide();
fields.subjectContainer.hide();
fields.timeZoneContainer.hide();
fields.colorContainer.hide();
fields.resourceContainer.hide();
fields.allDayContainer.hide();
fields.locationContainer.hide();
fields.fromContainer.hide();
fields.toContainer.hide();
fields.fromLabel.html("Start");
fields.toLabel.html("End");
var priceField = ''
var personsField = ""
priceField += "<div>"
priceField += "<div class='jqx-scheduler-edit-dialog-label'>Price</div>"
priceField += "<div class='jqx-scheduler-edit-dialog-field'><input type='number' id='price' step='0.01' /></div>"
priceField += "</div>"
personsField += "<div>"
personsField += "<div class='jqx-scheduler-edit-dialog-label'>Persons</div>"
personsField += "<div class='jqx-scheduler-edit-dialog-field'><input type='number' id='persons' /></div>"
personsField += "</div>"
var i = 0;
$('#dialogscheduler').children('div').each(function () { // loop trough the div's (only first level childs) elements in dialogscheduler
i += 1;
if (i == 2) { // places the field in the third position.
$(this).after(priceField);
$(this).after(personsField);
};
});
},
editDialogOpen: function (dialog, fields, editAppointment) {
console.info(dialog);
fields.repeatContainer.hide();
}
});
$('#scheduler').on('editDialogOpen', function (event) {
var args = event.args;
var appointment = args.appointment;
if(appointment){
$('#dialogscheduler > div').find('#price').val(appointment.price);
$('#dialogscheduler > div').find('#persons').val(appointment.persons);
}
else {
$('#dialogscheduler > div').find('#price').val(0);
$('#dialogscheduler > div').find('#persons').val(0);
$('#dialogscheduler > div').find('#from').val('');
$('#dialogscheduler > div').find('#to').val('');
$('#dialogscheduler > div').find('#description').val('');
$('#dialogscheduler > div').find('#status').val();
}
});
$('#scheduler').on('appointmentAdd', function (event) {
var price_data = $('#dialogscheduler > div').find('#price').val();
var persons_data = $('#dialogscheduler > div').find('#persons').val();
var a_type = event.args.appointment.status;
var description = event.args.appointment.description;
var start_date = event.args.appointment.from.toString();
var id = null;
var end_date = event.args.appointment.to.toString();
var availability = setAvailability(price_data,persons_data,start_date,end_date,id, a_type, description);
});
$('#scheduler').on('appointmentDelete', function (event) {
var id = event.args.appointment.id;
deleteEvent(id);
});
$('#scheduler').on('appointmentChange', function (event) {
var id = event.args.appointment.id;
var price_data = $('#dialogscheduler > div').find('#price').val();
var persons_data = $('#dialogscheduler > div').find('#persons').val();
var description = event.args.appointment.description;
var a_type = event.args.appointment.status;
var start_date = event.args.appointment.from.toString();
alert(start_date);
var end_date = event.args.appointment.to.toString();
var availability = setAvailability(price_data,persons_data,start_date,end_date,id, a_type,description);
});
}
})
function deleteEvent(pk) {
$.ajax({
url: "{% url 'delete-availability' %}",
method: "GET",
data: { pk : pk, business_pk:'{{form.instance.pk}}'},
dataType: "json",
success: function(response){
console.info(response)
}
})
}
I think you need to put the below code snippet in the editDialogOpen() function. This is working for me.
setTimeout(function() {
dialogRef.find("div").first().find("div").first().html("Create a new business schedule");
}, 10);
You can use the localization to do it. I'm using jqxScheduler with Angular, so:
Add [localization]="localization" into the component definition that should looks like:
<jqxScheduler #scheduler [editDialogCreate]="editDialogCreate" [localization]="localization">
Add a localization property into the component class. jqxScheduler has different titles for create and edit appointents:
localization = {
editDialogTitleString: 'Edit a business schedule',
editDialogCreateTitleString: 'Create a new business schedule'
};
jQWidgets has implementation examples to other languages. JQuery here.
$("#scheduler").jqxScheduler({
localization: {
editDialogCreateTitleString: "Create a new business schedule",
},
});
I try to build an input field for quantities with plus and minus buttons. More like to understand how composite controls are working. I found this documentation.
I thought I could use the new control like this:
new ex.perimental.Input({
width: "14em",
editable: true,
input: new sap.m.Input({
width: "8em",
value: {
path: "model>Quantity",
type: new sap.ui.model.type.Integer({}, {
minimum:0
})
},
description: "{model>Unit}"
}),
})
The control code looks like this:
sap.ui.define([
"sap/ui/core/Control",
"sap/m/Button",
"sap/m/Input"
], function(Control, Button, Input) {
"use strict";
return Control.extend("ex.perimental.Input", {
metadata: {
properties: {
width: {
type: "string",
defaultValue: "14em",
},
editable: {
type: "boolean",
defaultValue: false,
},
},
aggregations: {
_increaseButton: {
type: "sap.m.Button",
multiple: false,
visibility: "hidden",
},
_decreaseButton: {
type: "sap.m.Button",
multiple: false,
visibility: "hidden",
},
input: { type: "sap.m.Input", multiple: false },
_hBox: { type: "sap.m.HBox", multiple: false, visibility: "hidden" },
},
events: {
increase: {},
decrease: {},
},
},
_onDecrease: function(oEvent) {
var oResourceBundle = this.getModel("i18n").getResourceBundle();
var oldValue = this.getAggregation("input").getValue();
var newValue = 0;
if (!isNaN(Number(oldValue))) {
newValue = Number(oldValue) - 1;
}
oInput.setValue(newValue);
this.fireEvent("decrease", {
oldValue: oldValue,
newValue: newValue,
});
},
_onIncrease: function(oEvent) {
var oResourceBundle = this.getModel("i18n").getResourceBundle();
var oldValue = this.getAggregation("input").getValue();
var newValue = 0;
if (!isNaN(Number(oldValue))) {
newValue = Number(oldValue) + 1;
}
oInput.setValue(newValue);
this.fireEvent("increase", {
oldValue: oldValue,
newValue: newValue,
});
},
init: function() {
this.setAggregation(
"_decreaseButton",
new Button({
icon: "sap-icon://sys-minus",
press: this._onDecrease.bind(this),
})
);
this.setAggregation(
"_increaseButton",
new Button({
icon: "sap-icon://sys-add",
press: this._onIncrease.bind(this),
})
);
this.setAggregation(
"_hBox",
new sap.m.HBox({
items: [
this.getAggregation("_decreaseButton"),
this.getAggregation("_increaseButton"),
],
})
);
},
setEditable: function(sValue) {
debugger;
// aggregations will be null now
// I assume because they are reused in the HBox control
// this.getAggregation("_increaseButton").setEditable(sValue);
// this.getAggregation("_decreaseButton").setEditable(sValue);
// this.getAggregation("input").setEditable(sValue);
},
setWidth: function(sValue) {
this.getAggregation("_hBox").setWidth(sValue);
},
setInput: function(oInput) {
this.setAggregation("input", oInput);
var oHBox = this.getAggregation("_hBox");
oHBox.insertItem(oInput, 1);
},
renderer: function(oRenderManager, oControl) {
oRenderManager.write("<div");
oRenderManager.writeControlData(oControl);
oRenderManager.addClass("myStyle");
oRenderManager.writeClasses();
oRenderManager.write(">");
oRenderManager.renderControl(oControl.getAggregation("_hBox"));
oRenderManager.write("</div>");
}
});
});
It will be rendered but the setEditable is not working.
The buttons (used inside the HBox control again) are not reachable via getAggregation. Also the input field (set from outside) can't be accessed.
Not sure how to do it right. Anyone an idea?
Edit2
This is the latest version but still not working.
I am asking me how to put the externally defined input control into the right place inside the inner Hbox control and be able to access this control in methods like setEditable?
sap.ui.define([
"sap/ui/core/Control",
"sap/m/Button",
"sap/m/Input"
], function(Control, Button, Input) {
"use strict";
return Control.extend("ex.perimental.Input", {
metadata: {
properties: {
width: {
type: "string",
defaultValue: "14em",
},
editable: {
type: "boolean",
defaultValue: false,
},
},
aggregations: {
_hBox: { type: "sap.m.HBox", multiple: false, visibility: "hidden" },
},
associations: {
input: { type: "sap.m.Input", multiple: false, singularName: "input" },
},
events: {
increase: {},
decrease: {},
},
},
_onDecrease: function(oEvent) {
var oResourceBundle = this.getModel("i18n").getResourceBundle();
var oldValue = this._input.getValue();
var newValue = 0;
if (!isNaN(Number(oldValue))) {
newValue = Number(oldValue) - 1;
}
this._input.setValue(newValue);
this.fireEvent("decrease", {
oldValue: oldValue,
newValue: newValue,
});
},
_onIncrease: function(oEvent) {
var oResourceBundle = this.getModel("i18n").getResourceBundle();
var oldValue = this._input.getValue();
var newValue = 0;
if (!isNaN(Number(oldValue))) {
newValue = Number(oldValue) + 1;
}
this._input.setValue(newValue);
this.fireEvent("increase", {
oldValue: oldValue,
newValue: newValue,
});
},
init: function() {
this._decreaseButton = new Button({
icon: "sap-icon://sys-minus",
press: this._onDecrease.bind(this),
});
this._increaseButton = new Button({
icon: "sap-icon://sys-add",
press: this._onIncrease.bind(this),
});
this.setAggregation(
"_hBox",
new sap.m.HBox({
items: [
this._decreaseButton,
this.getAssociation("input"),
this._increaseButton,
],
})
);
},
setEditable: function(sValue) {
var bEditable = false;
if (sValue === true) {
bEditable = true;
}
this._decreaseButton.setEnabled(bEditable);
this._increaseButton.setEnabled(bEditable);
// seems not always working
this._input.setEditable(bEditable);
},
setWidth: function(sValue) {
this.getAggregation("_hBox").setWidth(sValue);
},
setInput: function(oInput) {
this.setAssociation("input", oInput);
this._input = oInput;
var oHBox = this.getAggregation("_hBox");
oHBox.insertItem(oInput, 1);
},
renderer: function(oRenderManager, oControl) {
oRenderManager.write("<div");
oRenderManager.writeControlData(oControl);
oRenderManager.addClass("myStyle");
oRenderManager.writeClasses();
oRenderManager.write(">");
oRenderManager.renderControl(oControl.getAggregation("_hBox"));
oRenderManager.write("</div>");
}
});
});
I still have problems with the association handling (updated code) I guess handling the association should be done different? Sometimes the input field is still null.
a control can only be aggregated by one control at a time.
This is the difference between associations (control may be at multiple at the same time) and aggregations.
What you can do in your init is:
this._decreaseButton = new Button (...)
Basically you only need one aggregation for your HBox.
If your buttons are then aggregated by the HBox they will know the models of the parent and also be destroyed.
The only thing you need to check if your Root control is a Ancestor of the created controls (use myControl.getParent()).
best regards,
Tobias