Unable to get save data event in ng2-smart-table - angular6

I am using ng2-smart-table for maintain data in my angular 6 app. As I seen in it's git and npm page. I have set my code like this way.
<ng2-smart-table
[settings]="settings"
[source]="characters"
(createConfirm)="onCreateConfirm($event)">
I am able to load data in table by call API. But when I am not able to get save data event. For that I have set function like this.
onCreateConfirm(event) {
alert("Clicked...");
}
I have set this function under the ngOnInit.

It's a common issue, you need to set in the configuration object the confirmCreate property, like this:
export const settings= {
delete: {
confirmDelete: true,
...
},
add: {
confirmCreate: true,
...
},
edit: {
confirmSave: true,
...
},
....

Related

Trying to get some position of JSON using Observables

Sorry for the question, but I'm newer in Typescript and Ionic and Im a bit confused about how should I proceed.
I have a JSON file with 150 entries based on an interface I'm declared quite simple:
export interface ReverseWords {
id: number;
todo: string;
solution: string;}
On the other hand, I have a service which reads the json file and returns an Observable of this type (ReverseWords)
getReverseWords() {
return this.http.get<ReverseWords>('/assets/data/reves.json');}
On .ts file, I call the service and I have all the content of the JSON file. What I want to do (and Im not able to do) is get only one entry based on a random position.
On .ts file:
reverseWords: Observable<ReverseWords>; // All the JSON content
reverseWordsSelected: Observable<ReverseWords>; // I would like to get one entry here
On ngOnInit():
this.reverseWords = this.dataservice.getReverseWords();
Everything is fine until here, I've got all the content and I can log it in console. I'm using Observables so I need to subscribe to it to get the information. And I use rxjs/operators pipe and filter to try it, but nothing is showing in the chrome developer console (not even an error).
const reverseWordSelectedByPosition = this.reverseWords.pipe(filter(reverseWord => reverseWord.id === randomPosition));
reverseWordSelectedByPosition.subscribe(console.log);
Could anybody help me and tell me what I'm doing wrong?
Other thing I've tested is to do the following in the service:
getReverseWords() {
return this.http.get<ReverseWords[]>('/assets/data/reves.json');}
And then in the .ts file:
reverseWords: Observable<ReverseWords[]>;
But I have the same problem.
Finally, the most weird thing is that if I write in the .ts file this simple test:
const test = from([
{
id: 1,
todo: 'chapter',
solution: 'r-e-t-p-a-h-c'
},
{
id: 2,
todo: 'claustrofobia',
solution: 'a-i-b-o-f-o-r-t-s-u-a-l-c'
},
{
id: 3,
todo: 'keyboard',
solution: 'd-r-a-o-b-y-e-k'
}
]);
Everything is fine and I can see on the log only 1 entry if I choose 2, for example.
Any help or advice??
Thanks and sorry for the long approach!!
As TotallyNewb suggested, I show an example of the JSON file, with only 3 entries:
[
{
"id": 1,
"todo": "chapter",
"solution": "r-e-t-p-a-h-c"
},
{
"id": 2,
"todo": "claustrofobia",
"solution": "a-i-b-o-f-o-r-t-s-u-a-l-c"
},
{
"id": 3,
"todo": "keyboard",
"solution": "d-r-a-o-b-y-e-k"
}
]
Since you are getting the whole array you can use map
this.reverseWords.pipe(
map((items) => items[Math.floor(Math.random() * items.length)]), // Creates a random index based on the array length
)
.subscribe(console.info);
If you want to pass the result to reverseWordsSelected, you can change it to a Subject and pass the value to it from the subscription of reverseWords with .next().
You can check out this stackblitz for a working example

Vue js external data object

I'm just starting out and have gone through the Vue guide. I've got some basic grasp on imports and exports of ES6 but wanted to know the ideal way of doing this.
I'll have several components that need an original single source of data that i'll need to individually manipulate from there. Ideally I want that data to be in a separate file so that others can manipulate it.
I can figure out to do this via jquery ( seen below ) but I don't really need to make a call as the json file will be internal:
module.exports = {
data: function () {
return {
msg: 'hello',
whatever : 'hi'
}
},
created : function() {
this.fetchData();
},
methods : {
fetchData : function() {
console.log("WORKING");
var self = this;
$.get( apiURL, function( data ) {
self.items = data;
console.log(data);
});
}
}
}
But I also don't want to have all the data be in the App.vue file. I need it somewhere else and then need it to replace my data.
Is the best way to do this to create another Vue file with no template or styling and just create it's own module.exports data object? Say mydata.vue:
module.exports = {
data: function () {
_mydata = {
items : [
{case:'caseone'},
{case:'casetwo'}
],
otheritems : [
{case:'caseone'},
{case:'casetwo'}
]
}
}
}
And then somehow replacing this data object in mydata.vue with the data object in app.vue with imports ( main. js ) ?
import Vue from 'vue'
import App from './App.vue'
import Data from './SiteData.vue'
Just wanted to check if this was the ideal way/i'm on the right path...or if there is an easier way to have a central data object in a different file for all my components?
What I have done is to manage my data in a json file. I think that the approach of use separate files for initial data is cool for small apps. Bigger apps need something more usefull like Vuex.
I don't think it is a good idea to manage a .vue file, as those files are meant to be handled by some module budled system, with the correspondind vue transformation, not the case of the data object.
My approach was this: I had a data.json file
data.json
{
"component1": {
"someData": "someValue",
...
},
...
"componentN": {
"someOtherData": "someOtherValue"
}
}
And then I import that data in the corresponding component
componentN.vue
<template>
</template>
<script>
import { componentN } from './data.json'
export default {
data () {
return componentN
}
}
</script>
Note that:
I used a single file for manage data, however you can split it in a file for every component, for example.
As you can see, this approach can become a mess with medium apps, I don't want to even imagin it in big apps, so be careful.

VueJS - trouble understanding .$set and .$add

I am trying to build an array of objects in VueJS and I am running into some issues with .$set and .$add.
For example, I need the following structure when adding new items/objects:
{
"attendees": {
"a32iaaidASDI": {
"name": "Jane Doe",
"userToken": "a32iaaidASDI",
"agencies": [
{
"name": "Foo Co"
}
]
}
}
}
New objects are added in response to an AJAX call that returns JSON formatted the same as above. Here is my Vue instance:
var vm = new Vue({
el: '#trainingContainer',
data: {
attending: false,
attendees: {}
},
methods: {
setParticipantAttending: function(data)
{
if (data.attending)
{
this.attendees.$add(data.userToken, data);
} else {
this.attendees.$delete(data.userToken);
}
}
}
});
This only works if I start with attendees: {} in my data but when I try attendees.length after adding an attendee, I receive undefined. If I use attendees: [], the new object does not appear to be added. And lastly, if I use .$set(data.userToken, data) it does not add in the 'token':{data..} format required.
What could be the issue here? What is the correct way to use $.add when starting with an empty array of objects?
UPDATE
I found that it works if I set attendees: {} and then, when adding a new object,
if (data.userToken in this.attendees) {
this.attendees.$set(data.userToken, data);
} else {
this.attendees.$add(data.userToken, data);
}
Not sure if there is a better way to accomplish this.
If you set attendees to an empty object ({}) it will not have a length attribute. That attribute is on Arrays.
If you set attendees to an empty array ([]) then you need to use $set (or really, I think you want .push()) – $add is intended for use on objects not on arrays.
I'm not quite following your last question – could you add more context?
EDIT 2:
The answer below was for Vue 1.x. For Vue 2.x and greater use:
this.$set(this.attendees, data.userToken, data);
More information here: https://v2.vuejs.org/v2/api/#Vue-set
EDIT:
Responding to your update, you should be able to just use $set in all cases. I.e. just do this:
this.attendees.$set(data.userToken, data);
As of version 0.6.0, this seems to be the correct way:
this.someObject = Object.assign({}, this.someObject, { a: 1, b: 2 })
http://vuejs.org/guide/reactivity.html#Change_Detection_Caveats

nodejs ractive and consolidate html comment issue

I am using consolidate.js and ractive templates, which by default strip out comments. I am trying to add some html logic in the page that does something like this:
<![if IE]>one thing<![endif]>
<![if !IE]>another thing<![endif]>
However ractive removes the comments. I know you can allow comments in ractive, by setting stripComments false, but I don't know how to do that through consolidate.js.
The second argument of consolidate.ractive() is passed directly to Ractive, so you can do this:
cons.ractive(path, { stripComments: false, user: 'Tobi' }, function () {});
In case you want to separate your data from Ractive config, you can do this instead:
cons.ractive(path, { stripComments: false, data: { user: 'Tobi' } }, function () {});
If the object doesn't have the data property, the whole object will be used as data as well.

jqGrid toolbar search with autocomplete using json data

I found the very nice demo by Oleg (http://www.ok-soft-gmbh.com/jqGrid/FillToolbarSearchFilter.htm) which shows a "jqGrid toolbar search with autocomplete using local data" but have trouble to get this to work for json via ajax. Is there a good reason why the autocomplete feature won't work - even if I force the grid to be local after loading?
$(document).ready(function() {
var mygrid = $("#mylist"),
mygetUniqueNames = function(columnName) {
var texts = mygrid.jqGrid('getCol',columnName), uniqueTexts = [],
textsLength = texts.length, text, textsMap = {}, i;
for (i=0;i<textsLength;i++) {
text = texts[i];
if (text !== undefined && textsMap[text] === undefined) {
// to test whether the texts is unique we place it in the map.
textsMap[text] = true;
uniqueTexts.push(text);
}
}
return uniqueTexts;
};
mygrid.jqGrid({
url:'autocompleteTest.php',
datatype: "json",
colNames:['name', 'City','stateCd'],
colModel:[
{name:'name',index:'name',width:225, search: true},
{name:'City',index:'City',width:125},
{name:'stateCd',index:'stateCd',width:75},
],
rowNum: 100,
loadonce : true,
sortname: 'name',
sortorder: 'desc',
sortable: true,
viewrecords: true,
rownumbers: true,
sortorder: "desc",
ignoreCase: true,
pager: '#mypager',
height: "auto",
caption: "How to use filterToolbar better with data from server"
}).jqGrid('navGrid','#mypager',
{edit:false, add:false, del:false, search:false, refresh:false});
mygrid.jqGrid('setColProp', 'name',
{
searchoptions: {
sopt:['bw'],
dataInit: function(elem) {
$(elem).autocomplete({
source:mygetUniqueNames('name'),
delay:0,
minLength:0
});
}
}
});
mygrid.jqGrid('filterToolbar',
{stringResult:true, searchOnEnter:true, defaultSearch:"bw"});
});
It is difficult to provide an example in case of the usage of remote source parameter of jQuery UI Autocomplete. The main problem is that your question is about jqGrid which is pure JavaScript solution. If we would discuss the server part of tha solution we would have too options. Many users uses different languages: Java, C#, VB, PHP and so on. For example I personally prefer C#. Then we would have to choose the technology which we use: ASP.NET MVC, WCF, ASPX web service and so on. For example I would choose WCF. Then we should define the database access technology, for example, Entity Framework, LINQ to SQL, SqlDataReader, SqlDataAdapter and so on. Let us I would choose Entity Framework and would provide you the corresponding code example, but it would help you not really if you use for example PHP and MySQL.
So I just describe which interface should have the server for the remote source parameter of jQuery UI Autocomplete without any code.
You should replace in my example the source parameter to your server url like following:
dataInit: function(elem) {
$(elem).autocomplete({
source:'yourSearchUrl.php',
minLength:2
});
}
If the user types two characters (the value can be changed by minLength option), for example 'ab' then the autocomplete will make HTTP GET request with the parameter term=ab:
yourSearchUrl.php?term=ab
your server should answer with the JSON data in the same format as for the local source. I used the string array format in my previous example. Another supported format is array of objects with label/value/both properties like
[
{
"id": "Dromas ardeola",
"label": "Crab-Plover",
"value": "Crab-Plover"
},
{
"id": "Larus sabini",
"label": "Sabine`s Gull",
"value": "Sabine`s Gull"
},
{
"id": "Vanellus gregarius",
"label": "Sociable Lapwing",
"value": "Sociable Lapwing"
},
{
"id": "Oenanthe isabellina",
"label": "Isabelline Wheatear",
"value": "Isabelline Wheatear"
}
]
read the documentation for more information.
If you need to implement more complex scenario and send some additional data to the server or convert the server response in any way you can use custom source callback function. In the case you should use source: function(request, response) {/*your implementation*/}, where the request would be an object having term property (request.term). Inside of your implementation your should make ajax request to the server manually. The response would be callback function which you should call after your custom ajax request will be finished (inside of success event handler). The response function should be called with the parameter which should be array in the same format as mygetUniqueNames returns. I recommend you to examine the source code from the jQuery Autocomplete demo.
To de able to provide unique data from one column of tabele you should just use SELECT DISTINCT SQL statement which are supported in the most databases.
I hope that my description would help you.
UPDATED: If you have the local source the solution you could find in my old answer which you already use. What you just need to do is to call the filterToolbar after the source array are filled. Because you load the data from the server your should move the call of filterToolbar inside of loadComplete. You use loadonce:true jqGrid option which switch the datatype from 'json' to 'local' after the first data loading. So you can include in the loadComplete event handler of your grid the code like the following:
var grid = $('#list');
grid({
url:'autocompleteTest.php',
datatype: 'json',
loadonce: true,
// ... other parameters
loadComplete: function(data) {
if (grid.getGridParam('datatype') === 'json') {
// build the set 'source' parameter of the autocomplete
grid.jqGrid('setColProp', 'name', {
searchoptions: {
sopt:['bw'],
dataInit: function(elem) {
$(elem).autocomplete({
source:mygetUniqueNames('name'),
delay:0,
minLength:0
});
}
}
});
mygrid.jqGrid('filterToolbar',
{stringResult:true,searchOnEnter:true,
defaultSearch:"bw"});
}
}
});
If you will need to reload the data from the server (change the datatype to 'json' and call grid.trigger('reloadGrid')) you will have to change the code above so that you first destroy the autocomplete widget with $('#gs_name').autocomplete('destroy') and then create it one more time with the same code like inside of dataInit.