TypeScript nesting static properties - javascript

I'm trying to build a class that will contain constant values to be used at different places.
The structure should be something like this:
class JavascriptEvents {
static change: string = "change";
static click: string = "click";
static blur: string = "blur";
static inputChange: string = "input propertychange paste";
static dblClick: string = "dblclick";
static bootstrap: Object = {
accordion: {
show: "show.bs.collapse",
shown: "shown.bs.collapse",
hide: "hide.bs.collapse",
hidden: "hidden.bs.collapse"
},
modal: {
shown: "shown.bs.modal",
show: "show.bs.modal",
hide: "hide.bs.modal",
hidden: "hidden.bs.modal",
loaded: "loaded.bs.modal"
}
}
}
Question: How should the bootstrap part be nested so I can reference an event like:
$("someElement").on(JavascriptEvents.bootstrap.modal.shown, function(){
// do whatever needed
});

I think the problem is the : Object declaration, which hid all the type information from the call site. If you simply remove it, the type checker should be happy again.
E.g.:
class JavascriptEvents {
static bootstrap: Object = {
modal: {
shown: "shown.bs.modal",
}
}
static bootstrap2 = {
modal: {
shown: "shown.bs.modal",
}
}
}
let jq: any;
jq.on(JavascriptEvents.bootstrap.modal.shown); // Error
jq.on(JavascriptEvents.bootstrap2.modal.shown); // Works
Playground

Related

Can't call class properties inside inline script tag

I have a Javascript class inside my global.js like this:
class CustomModal extends ModalDialog {
constructor() {
super();
this.modals = [{
name: 'quick-select',
title: 'Quick Select',
},
{
name: 'main-menu',
title: 'Menu',
},
{
name: 'notify-me',
title: 'Notify When Back in Stock',
},
];
}
}
window.CustomModal = CustomModal;
Now I want to access the class properties from outside the class inside an inline script tag, like this:
<script>
document.addEventListener('DOMContentLoaded', function() {
console.log('window.CustomModal.modals', window.CustomModal.modals)
});
</script>
but I'm getting undefined. What am I doing wrong?
I want to access properties and functions. I also want to change variables. My main goal is to add another modal to the array, like this:
<script>
document.addEventListener('DOMContentLoaded', function() {
window.CustomModal.modals.push({ name: 'new-modal', title: 'New Modal' });
});
</script>
Thanks in advance!
You defined a class, hence you should instantiate it:
window.CustomModal = new CustomModal();
In your attempt, you only set a reference of the prototype of that class.

Angular Slickgrid | How to disable the row selection of checkboxSelector of selectableOverride dynamically

Want to disable the selected row items by updating the gridOptions after some button clicks.
initGridOptions() {
this.gridOptions = {
enableSorting: true,
enableFiltering: true,
enablePagination: true,
enableAutoResize: true,
autoResize: {
containerId: 'grid-wrapper',
sidePadding: 5
},
alwaysShowVerticalScroll: false,
enableCheckboxSelector: true,
enableRowSelection: true,
checkboxSelector: {
hideInFilterHeaderRow: false,
hideInColumnTitleRow: true,
},
rowSelectionOptions: {
// True (Single Selection), False (Multiple Selections)
selectActiveRow: false
}
}
}
//prepareGrid() { ...... }
disableButtonClick() {
this.gridObj.setOptions({
checkboxSelector: {
selectableOverride: (row: number, dataContext: any, grid: any) => {
// validate each row and disable the selected rows
return false;
}
}
});
}
Stackblitz Demo
I'm not sure if you can toggle the checkbox column without removing it (maybe with grid.setColumns() but it's probably better to just use the selectableOverride callback. It will allow you to dynamically change its usability on the fly (see the Wiki) and in your case just use your boolean flag to have the callback return true or false (the later will disable/remove all checkboxes)
export class Example1 implements OnInit {
prepareGrid() {
this.gridOptions = {
enableRowSelection: true,
enableCheckboxSelector: true,
checkboxSelector: {
// you can override the logic for showing (or not) the expand icon
// for example, display the expand icon only on every 2nd row
selectableOverride: (row: number, dataContext: any, grid: any) => (dataContext.id % 2 === 1)
},
multiSelect: false,
rowSelectionOptions: {
// True (Single Selection), False (Multiple Selections)
selectActiveRow: true,
},
};
}
}
As per the new comments and the stachblitz, you need to have only 1 common method and in that method you do different logic depending on what button is clicked outside. For example, if I take some code from your demo, let's use a new flag showOnlyOddRows = false and let say that when you click your external button it will turn that flag to true and as we can expect it will re-render the grid and only show the row selection on odd rows
export class AppComponent implements OnInit {
showOnlyOddRows = true;
ngOnInit(): void {
this.gridOptions = {
checkboxSelector: {
hideInFilterHeaderRow: true,
hideInColumnTitleRow: false,
selectableOverride: this.validateRowSelection.bind(this)
// or
// selectableOverride: (row: number, dataContext: any) => this.validateRowSelection(row, dataContext),
},
// ...
};
}
validateRowSelection(row: number, dataContext: any, grid: any) {
return this.showOnlyOddRows ? dataContext.id % 2 === 1 : true; // returning true means that we want to show the row selection
}
// change flag when external button is clicked and re-render grid with new row selection set
disableOddRows() {
this.showOnlyOddRows = true;
this.gridObj.invalidate(); // this will re-execute the validateRowSelection method
}
So again, do not change the override with setOptions, it will completely break the code, so don't do that. If you really need to change options of the plugin, you should use the plugin setOptions not the grid.setOptions. Something like this.angularGrid.extensionService.getSlickgridAddonInstance(ExtensionName.checkboxSelector).setOptions({ /* ... */ }) or this.angularGrid.extensionService.getSlickgridAddonInstance(ExtensionName.checkboxSelector).selectableOverride = newOverrideFn ... but again I probably wouldn't do that, it's easier to just keep 1 method with different logic inside it (like validateRowSelection shown earlier)

Generating TinyMCE drop-down menu dynamically

I am trying to create toolbar button in TinyMCE with options that are derived from the array. I've followed the examples on Tiny's website and the button is getting generated as expected. Here is the code:
var mergeFields = {one: "first", two: "second", three: "third"};
tinymce.init({
selector: 'textarea',
menubar: false,
toolbar: 'mergefields',
setup: function (editor) {
editor.ui.registry.addMenuButton('mergefields', {
text: 'Merge Fields',
fetch: function (callback) {
var items = [];
for (var fieldName in mergeFields) {
var menuItem = {
type: 'menuitem',
text: mergeFields[fieldName],
onAction: function() {
// The problem: this function always inserts the last element of the array
// instead of the expected fieldName associated with this menuItem
editor.insertContent(fieldName);
},
};
items.push(menuItem);
}
callback(items);
},
});
}
});
<script src="https://cloud.tinymce.com/5/tinymce.min.js?apiKey=XXXXX"></script>
<textarea>Editor</textarea>
The problem happens when one of the options is selected and the anonymous function assigned to onAction property is executed -- it always inserts "three" into the document (presumably because after running through the whole array, fieldName is set to "three"). How can I make the onAction handler insert the right value into the document?
This needs to work in TinyMCE 5.
I've found a similar question here: Adding custom dropdown menu to tinyMCE and insert dynamic contents, but it was referring to TinyMCE 4 and unfortunately the provided answer does not work for TinyMCE 5.
Thanks for your help!
I had the same problem.
I solved it using value+onSetup
https://jsfiddle.net/stvakis/tjh7k20v/8/
var mergeFields = {
one: "first",
two: "second",
three: "third"
};
tinymce.init({
selector: 'textarea',
menubar: false,
toolbar: 'mergefields',
setup: function(editor) {
editor.ui.registry.addMenuButton('mergefields', {
text: 'Merge Fields',
fetch: function(callback) {
var items = [];
for (var fieldName in mergeFields) {
var menuItem = {
type: 'menuitem',
text: mergeFields[fieldName],
value:fieldName,
onSetup: function(buttonApi) {
var $this = this;
this.onAction = function() {
editor.insertContent($this.data.value);
};
},
};
items.push(menuItem);
}
callback(items);
},
});
}
});

Override JavaScript class prototype inside a JavaScript class

I tried to override the Text class prototype function doSomething.
The class Editor initialises its txt with Text inside the _initText function.
The issue is my override code has never been really taken and overridden the original code.
No errors, when I run editor.txt.doSomething() it still print the "old message".
Please help on how to override this type of prototype in JavaScript. Plenty thanks.
editor.js
<!-- language: lang-js -->
function Text(editor) {
this.editor = editor;
}
Text.prototype = {
constructor: Text,
init: function init() {
this.doSomething();
},
doSomething: function doSomething() {
console.log('old message');
},
};
function Editor(editor) {
this.editor = editor;
}
Editor.prototype = {
constructor: Editor,
_initText: function _initText() {
this.txt = new Text(this);
this.txt.init();
},
init: function init() {
this._initText();
}
};
extension.js
<!-- language: lang-js -->
// When DOM is loaded
Text.prototype.doSomething = function() {
console.log('new message');
};
index.html
<!-- language: lang-html-->
// When DOM is loaded
editor = new Editor();
editor.init();

Data model is not getting deserialised in controller

Here is my model class
public class ProductModel
{
public Product {set;set;} // Product is one more class
}
I am using below javascript code to get partial view but 'model' is not getting deserialised in controller...What I am missing?
Storing data in a HTML attribute as shown below
JavaScriptSerializer serializer = new JavaScriptSerializer();
var jsonObject = serializer.Serialize(obj)
<span data-singleproduct="#jsonObject" id="#mprodid" class="ShowProductModal">Find out more..</span>
Used jQuery to call partial page and popup
$('.ShowProductModal').on('click', function () {
var model = $(this).data('singleproduct');
//I can see data of variable model here in developer tool
$("#ProductModal").dialog({
autoOpen: true,
position: { my: "center", at: "top+350", of: window },
width: 1000,
resizable: false,
title: '',
modal: true,
open: function () {
$(this).load('ShowProductModal', model );
},
buttons: {
}
});
return false;
});
Here is my controller code
public PartialViewResult ShowProductModal(ProductModel product)
{
return PartialView("ProductModal", product);
}
product always comes as null!!!
If I change ProductModel to Product , then it will work... ! CAN SOMEONE HELP ME?
public PartialViewResult ShowProductModal(Product product)
{
return PartialView("ProductModal", product);
}
You should try
$(this).load('ShowProductModal', { product: model });
And declare your method like this:
[HttpPost]
public PartialViewResult ShowProductModal([FromBody] JObject data)
{
var product = data["product"].ToObject<ProductModel>();
return PartialView("_SC5ProductModal", product);
}

Categories

Resources