How to add my own completer in ace editor - ace-editor

Now i am developing a simple web-based editor for my database backend. I found that ace comes with autocompleter, if I only need to do complete with SQL keywords, how should I add my own rules?

First, Activate the enableLiveAutocompletion as you mentioned, and you also have to ensure enableBasicAutocompletion is defined and set to true (see below).
editor.session.setMode("ace/mode/sql");
editor.setOptions({
enableBasicAutocompletion: true,
enableSnippets: true,
enableLiveAutocompletion: true
});
To add a new completer, do what eemp mentioned on github (here).
let langTools = ace.require('ace/ext/language_tools');
Then use the addCompleter method to add the completions as defined below:
var customCompleter = {
getCompletions: function(editor, session, pos, prefix, callback) {
// your code
/* for example
* let TODO = ...;
* callback(null, [{name: TODO, value: TODO, score: 1, meta: TODO}]);
*/
}
}
langTools.addCompleter(customCompleter);
You can also go have a look at the following:
Ace docs on Completers.

Just add:
editor.session.setMode("ace/mode/sql");
editor.setOptions({
enableBasicAutocompletion: true,
enableSnippets: true,
enableLiveAutocompletion: true
});
the enableLiveAutocompletion attribute will allow realtime popup

Related

Cypress conditional statement for a disabled button element

Trying to click a button based on another element with enabled/disabled status. For some reason, my disabled check code is not working and it always ends in another statement ('No existing routes found') even though the UI has a select button enabled.
cy.get('voyage-suggested-routes')
.find('button.selectButton')
.then(($routes) => {
if ($routes.is(":disabled")) {
cy.log("No existing routes found...")
} else {
cy.log("Deleting......")
cy.get('.delete-button').click({ force: true, multiple: true })
}
});
This is the DOM: (There are 3 elements by default and a delete option will be there for each Select button if it is not disabled.)
<button class="selectButton" disabled route="1">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="..."></path></svg>
SELECT
</button>
Tried the jquery method as well but the same result.
var btnStatus = Cypress.$('.selectButton')
.is(":disabled");
if (btnStatus == true) {
cy.log("Deleting......")
cy.get('.delete-button').click({ force: true, multiple: true })
} else {
cy.log("No existing routes found...")
}
What am I missing?
Update 1:
After Electron's input, my new code is:
cy.get('voyage-suggested-routes')
.find('button.selectButton')
.then(($routes) => {
if ($routes.is(":disabled").length === 0) {
cy.log("No existing routes found...")
} else {
cy.log("Deleting......")
cy.get('.delete-button').click({ force: true, multiple: true })
}
});
From the docs jQuery .is()
Description: Check the current matched set of elements against a selector, element, or jQuery object and return true if at least one of these elements matches the given arguments.
So if only one route is disabled, the delete will not go ahead.
Try using a filter to see if any are disabled.
cy.get('voyage-suggested-routes')
.find('button.selectButton')
.then(($routes) => {
const disabled = $routes.filter(":disabled")
if ($routes.length === disabled.length) {
cy.log("No existing routes found...")
} else {
cy.log("Deleting......")
cy.get('.delete-button').click({ force: true, multiple: true })
}
})
It's because you need each instead of then, like this:
.each(($routes) => {
in order to perform as many actions as there are button elements.
Edit: as Electron stated in the comments, the suggestion below will fail a test if all buttons are disabled, so take care if you use it.
And to better optimize your code, your can set the selector as .find('button.selectButton:not(:disabled)') then you don't need if block at all, just the delete statement.
Here's a custom command which conditionally runs a callback, depending on the result of filtering by given selector.
Not a lot of difference to .then(($routes) => { const disabled = $routes.filter(":disabled") pattern. Unfortunately ending part of a chain is quite difficult, as the whole test is considered one chain.
Cypress.Commands.add('maybe', {prevSubject:true}, (subject, selector, callback) => {
const result = subject.filter(selector)
if (result.length > 0) {
cy.log(`Maybe: Found ${result.length} "${selector}"`)
cy.wrap(result).then(callback)
return
}
cy.log(`Maybe: Not found: "${selector}"`)
})
cy.get('button.selectButton')
.maybe(':not(:disabled)', ($result) => {
// can use result of filter here
console.log('result is', $result))
// or conditionally run some other commands
cy.log(`Deleting...`)
cy.get('.delete-button').click({ force: true, multiple: true })
})
// runs either way
cy.wrap('something')
.then(x => console.log('next', x))

Is there a way to add a global directive for NS elements?

NativeScript provides a method to add custom properties to a component of your choice as mentioned here: https://docs.nativescript.org/core-concepts/properties.
Is there any way to add a custom property to all existing components? Just like Angular ng directives.
I'm using NS with plain JS.
EDITED: Added working code sample.
app.js
const application = require("tns-core-modules/application");
const Property = require("tns-core-modules/ui/core/properties").Property;
const View = require("tns-core-modules/ui/core/view").View;
const hiddenProperty = new Property(
{
name: "hidden",
defaultValue: false,
affectsLayout: true,
valueChanged: (target, oldValue, newValue) =>
{
console.log("New value is: " + newValue);
},
});
hiddenProperty.register(View);
application.run({ moduleName: "app-root" });
/*
Do not place any code after the application has been started as it will not
be executed on iOS.
*/

Reactive Form SetValue for FormGroup Array inside observable subscribe method

I am new the Angular but I am trying to understand How can we use Reactive Form and FormGroups array while we use the Service Observable.
My form is very simple, It has list of Articles, where you can select one of them and can edit the detail. It also has feature to add new article.
So, starting of the page itself, It has list of articles in left side and reactive blank form on other side.
Now, this form also contain some of the checkbox which provides the tags for an article.
Now, when I load the page, everything is coming as expected. Articles are coming and reactive form is also loading along with all the tags (un-checked)
When I click any of the article to make that editable, I am getting an error
"Must supply a value for form control at index: 0."
I tried to change the code little but but with that the new error started coming
"Must supply a value for form control with name: 'articleId'"
So, overall I am not getting what is fundamental issue. Seems like I am missing to give a name to the formgroup but not sure how to supply.
// Global Variables: Called from the constructor.
articleDetailForm: FormGroup;
tagFormArray: FormArray = new FormArray([]);
// While this.loadArticle(this.selectedArticleId); called on change event
private loadArticle(selectedArticleID: string) {
this.articleService.getArticle(selectedArticleID)
.subscribe(
(data: ArticleViewModel) => {
const _a = new ArticleViewModel(data);
debugger;
this.articleDetailForm.setValue({
articleBasicDetail: this.setBasicDetailForSelectedArticle(_a),
articleTagDetail: this.setTagDetailForSelectedArticle(_a.ArticleTagViewModels)
})
},
(err) => {
console.log(err);
});
}
private setBasicDetailForSelectedArticle(articleVM: ArticleViewModel) {
return new FormGroup({
articleId: new FormControl(articleVM.articleTitle, ),
articleTitle: new FormControl(articleVM.articleTitle),
articleContent: new FormControl(articleVM.articleContent)
});
}
private setTagDetailForSelectedArticle(articleTagsVM: ArticleTagViewModel[]) {
// want to loop through variable and checked only those tags which are available for this article
return new FormGroup({
tagId: new FormControl(111),
tagName: new FormControl("111"),
isChecked: new FormControl(true)
});
}
private createArticleDetailForm() {
let articleId = 'Dummy ID';
let articleTitle = 'Dummy Title';
let articleContent = 'Dummy Content';
this.articleDetailForm = this.formBuilder.group({
articleBasicDetail: this.formBuilder.group({
articleId: [{ value: articleId, disabled: true }, Validators.required],
articleTitle: [articleTitle, Validators.required],
articleContent: [articleContent, Validators.required],
}),
articleTagDetail: this.tagFormArray
});
}
ERROR Error: Must supply a value for form control with name: 'articleId'.
ERROR Error: "Must supply a value for form control at index: 0."

jqgrid frozenColumns + (cell Edit & sortable/reordering of non frozen columns)

Please guide me on a work around for having a set of columns frozen and the rest having cell edit feature along with column reordering/ show- hide options using jqgrid.
Thank You.
Please try this, simple solution,
Hide or remove cellEdit: true
Then add the below lines in above and below the setFrozenColumns
Previous code:
$("#jqGrid2").jqGrid('setFrozenColumns');
New Code:
$("#jqGrid2").jqGrid("setGridParam", {cellEdit: false, sortable: false});
$("#jqGrid2").jqGrid('setFrozenColumns');
$("#jqGrid2").jqGrid("setGridParam", {cellEdit: true, sortable: true});
The problem is that the current implementation of setFrozenColumns have some restrictions. Editing (in any editing mode) and sortable: true is not allowed for frozen columns, but setFrozenColumns. Moreover sortable: true should don't allow to resort headers of frozen columns. On the other side setFrozenColumns contains simple test of some parameters (see here) and the method do nothing if some such parameters (like cellEdit or sortable) are set.
I suggested in the post (with the demo) the way how to implement a workaround. The way is modification of approach from the answer and this one.
I find your question interesting and so I created the demo which demonstrates how one do can implement your requirements. It displays the following results (animated gif):
It uses mostly the following code
// create the grid
$grid.jqGrid({
...
});
$grid.bind("jqGridLoadComplete jqGridInlineEditRow jqGridAfterEditCell jqGridAfterRestoreCell jqGridInlineAfterRestoreRow jqGridAfterSaveCell jqGridInlineAfterSaveRow", function () {
fixPositionsOfFrozenDivs.call(this);
});
$grid.jqGrid("setGridParam", {cellEdit: false, sortable: false});
$grid.jqGrid("setFrozenColumns");
$grid.jqGrid("setGridParam", {cellEdit: true, sortable: true});
fixPositionsOfFrozenDivs.call($grid[0]);
try {
var p = $grid.jqGrid("getGridParam"), tid = $.jgrid.jqID(p.id), colModel = p.colModel, i, n = colModel.length, cm,
skipIds = [];
for (i = 0; i < n; i++) {
cm = colModel[i];
if ($.inArray(cm.name, ["cb", "rn", "subgrid"]) >=0 || cm.frozen) {
skipIds.push("#jqgh_" + tid + "_" + $.jgrid.jqID(cm.name));
}
}
$grid.jqGrid("setGridParam", {sortable: {options: {
items: skipIds.length > 0 ? ">th:not(:has(" + skipIds.join(",") + "),:hidden)" : ">th:not(:hidden)"
}}});
$grid.jqGrid("sortableColumns", $($grid[0].grid.hDiv).find(".ui-jqgrid-labels"));
} catch (e) {}

jqGrid change search filters on submit

I would like to alter the search filters after a user has submitted them. Normally jqGrid returns name in colmodel as the value for field, I would like to change this behavior for a specific column:
I would like to change:
{"groupOp":"AND","rules":[{"field":"available","op":"eq","data":"true"}]}
to
{"groupOp":"AND","rules":[{"field":"s.trait.available","op":"eq","data":"true"}]}
I have tried altering the submitted form in the ways below; firebug shows that the functions are never being called.
var searchOptions = {
multipleSearch:true, multipleGroup:false, closeOnEscape:true, closeAfterSearch:true,
sopt:['ge', 'eq', 'le'],
beforeSubmit:function (params, postdata) {
//alterations would be here
}
,
onclickSubmit:function (params, postdata) {
//alterations would be here
}
}
This approach works for editOptions and delOptions, I am not sure why I cannot get this to work for searching.
If you use the searching toolbar you can use beforeSearch callback to modify the postData.filter. In case of Singe Field searching or Advanced Searching you can use onSearch.
In the answer you can see how the postData.filter can be modified.
UPDATED: You did something wrong in your tests. The only problem is that the current implementation of searching don't initialize this to the grid, but it's not explicitly documented somewhere.
I created the demo for you which demonstrate that you do can modify the filter before relaoding of the grid will be started. If you would search in the grid for 'Client' equal to 300 the search request will be modified to 'amount' equal to 300 and you would see the results
The corresponding code is
$('#list').jqGrid('navGrid', '#pager', {add: false, edit: false, del: false}, {}, {}, {},
{
multipleSearch: true,
overlay: 0,
onSearch: function () {
var i, l, rules, rule, $grid = $('#list'),
postData = $grid.jqGrid('getGridParam', 'postData'),
filters = $.parseJSON(postData.filters);
if (filters && typeof filters.rules !== 'undefined' && filters.rules.length > 0) {
rules = filters.rules;
for (i = 0; i < rules.length; i++) {
rule = rules[i];
if (rule.field === 'name') {
// make modifications only for the 'contains' operation
rule.field = 'amount';
}
}
postData.filters = JSON.stringify(filters);
}
}});

Resources