how to give button on spreadsheet?

I want to implement a functionality where user can make changes to spreadsheet and whatever changes they made will be updated to database on button click on which I will call ajax, can anyone tell me how to add button over spreadsheet?

Hey @priyatama, unfortunately there is currently no way to add other views over the spreadsheet. However, this is a feature we’ve been looking into for some time, and it might come out at some point in the future. For now though, you can just add that button anywhere beside the spreadsheet in your layout: https://snippet.webix.com/lddrl1ku.

Or alternatively, you can add a button inside the toolbar: https://snippet.webix.com/t5wg6j4i.

If your question was concerning the actual implementation of the manual update functionality (saving data in your case) of the spreadsheet data, you can just add a button that will perform a webix.ajax().post() request with your data on click. Please take a look at this example: https://snippet.webix.com/8kh84efs.

I wanted to add button over toolbar. Can I style that button? May be just a color change. also can I save spreadsheet data on that button click?

If you take a look at the method I’ve described above you can see that we’re adding a standart Webix UI button view inside the toolbar, so any customization that would apply to the button will apply here. For instance you can apply a css property to give this button a css class, so you can refer to it and style it. This way, we can the set the color of our button (please note, that we have to add !important in this case to override the default rules):

  .test button.webix_button {
  	background: orange !important;
  }

And of course, you can add the needed functionality on top via click, we can just take our example with data saving from above and implement it here: https://snippet.webix.com/cq4woau3. Please take a look at this example, the data your put in won’t save unless you press the Save button on the toolbar, you can also note we’ve changed the color of our button to orange.

var sheet = webix.ui({
rows: [{
view: “button”, value: “Update”, width: 200
}, {
view:“spreadsheet”,
id:“ss”,
toolbar:“full”,
liveEditor:true,
sheetTabWidth:150,
data: myJavaScriptArray,
container: “webixsheetCx”,

					on:{

						onContextMenuConfig:function(ev){
							if (ev.area == "column" || ev.area == "row") return false;
							if (ev.area == "data")
								ev.data = [
									{ id:"com-1", group:"myContext", value:"Edit Standard Skill" },
									{ id:"com-2", group:"myContext", value:"Non-Standard Skill" },
									{ id:"com-3", group:"myContext", value:"Command 3" }
								];
						},
						onCommand:function(obj){
							if (obj.group == "myContext")
								if (obj.id == "com-1") { $('#form-content-labsure').modal('show'); }

						}							
						
						
						
					}  

}]
});

This is my code, Is anything wrong here, because using this , it’s giving me error for ‘sheet’.

It gives me error to this line ->const editor = sheet.$$(“liveEditor”);

It looks like you are trying to refer to the liveEditor part of the spreadsheet, which would obviously work if you were to reference it from within your spreadsheet. However, your sheet variable is actually a layout in this case, which would mean sheet.$$("liveEditor") is trying to look for an inner id liveEditor inside a layout, which doesn’t exist. To avoid this, either refer to the spreadsheet directly via id or reassign the variable to point to the spreadsheet itself. Here’s an example: https://snippet.webix.com/n5mf67a2.

This removed my error in console but spreadsheet is not getting load.

Please provide a snippet with your code so I would be able to tell what the problem actually is. If you take a look at the example I’ve posted using your code above, the spreadsheet is loading just fine.

Please find my below code.

var sheet = webix.ui({
rows: [
{
view: “button”, value: “Update”, width: 200
},
{
view:“spreadsheet”,
id:“ss”,
toolbar:“full”,
liveEditor:true,
sheetTabWidth:150,
data: myJavaScriptArray,
container: “webixsheetCx”,

  on:{

    onContextMenuConfig:function(ev){
      if (ev.area == "column" || ev.area == "row") return false;
      if (ev.area == "data")
        ev.data = [
          { id:"com-1", group:"myContext", value:"Edit Standard Skill" },
          { id:"com-2", group:"myContext", value:"Non-Standard Skill" },
          { id:"com-3", group:"myContext", value:"Command 3" }
        ];
    },
    onCommand:function(obj){
      if (obj.group == "myContext")
        if (obj.id == "com-1") { $('#form-content-labsure').modal('show'); }
    }                           
  }  
}] 

});

const editor = $$(“ss”).$$(“liveEditor”);
/* OR
var sheet = spreadsheet
const editor = spreadsheet.$$(“liveEditor”);
*/
console.log(editor);

var alpha = “ABCDEFGHIJKLMNOPQRSTUVWXYZ”;
var decode = [];
var encode = [];
for (var i=1; i<1000; i++){
var prefixIndex = parseInt((i-1)/alpha.length);
var str = (prefixIndex?alpha[prefixIndex-1]:"")+alpha[(i-1)%(alpha.length)];

decode[str] = i;
encode[i] = str;
}

sheet.attachEvent(“onCommand”, function(action, start, end){
if (action.id == “add” || action.id == “del”){
var area = sheet.$$(“cells”).getSelectArea();
if(area && !(start && end)){
start = area.start;
end = area.end;
}

if (start && end){
  var data = sheet.serialize({sheets:true});
  var name = sheet.getActiveSheet();
  data.forEach(function(item){
    if(item.name != name){
      var regexp = new RegExp(name+"!(.*?)[0-9]{1,}", "g");
      item.content.data.forEach(function(data){
        if(data[2][0] == "="){
          var parts = data[2].match(regexp);
          parts.forEach(function(part){
            var old = part;
            var newVal = part.replace(name+"!","");
            var row = newVal.match(/\\${0,1}[0-9]{1,}/)[0];
            var col = newVal.match(/\\${0,1}[^0-9^\\$]{1,}/)[0];
            if(action.group == "column" && col[0] != "$"){
              col = decode[col];
              col += (end.column - start.column + 1) * (action.id == "add" ? 1 : -1);
              data[2] = data[2].replace(old, name+"!"+encode[col]+row);
            }
            else if(action.group == "row" && row[0] != "$"){
              row *= 1;
              row += (end.row - start.row + 1) * (action.id == "add" ? 1 : -1);
              data[2] = data[2].replace(old, name+"!"+col+row);
            }
          });
        }
      });
    }
  });
  sheet.parse(data);
  sheet.showSheet(name);
}

}
});

function endEdit(st){
if (editor.isEnabled()){
editor.updateCellValue();
editor.setValue(st ? sheet.getCellValue(st.row, st.column) : “”);
}
return true;
}

var updateCellValue = editor.updateCellValue;
editor.updateCellValue = function(){
const newv = this.getValue();
if(editor.realSheet && editor.realSheet != sheet.getActiveSheet()){
sheet.showSheet(editor.realSheet);
editor.realSheet = null;
editor.realValue = null;
sheet.$handleSelection = null;
editor.setValue(newv);
}
updateCellValue.apply(this, arguments);
}

sheet.attachEvent(“onBeforeSheetShow”, function(){
const val = editor.getValue();
if(editor.expectOperator()){
if(!editor.realSheet)
editor.realSheet = sheet.getActiveSheet();
editor.realValue = val;
webix.delay(()=>{
editor.setValue(val);
editor.focus();
sheet.$handleSelection = function(stCoord, endCoord, st, end){
let activeSheet = sheet.getActiveSheet();
activeSheet = editor.realSheet != activeSheet ? activeSheet+"!" : “”;
if (st == end){
if (!editor.expectOperator()) return endEdit(stCoord);
editor.setRange(activeSheet+end);
webix.delay(() => editor.focus());
}
else{
if (!editor.expectRange()) return endEdit(stCoord);
editor.setRange(${activeSheet+st}:${activeSheet+end});
webix.delay(() => editor.focus());
}
return false;
};
});
}
});

	});

Things I can see at a quick glance that are wrong here:

1 You are still referring to the variable sheet when it is a layout in our case, if you want to use that variable still, simply assign it to our spreadsheet instead:

var sheet = $$("spreadsheet");

2 I would also like to note that it looks like you are trying to use a template string here:

 editor.setRange(${activeSheet+st}:${activeSheet+end});

but you are forgetting about the backticks (`), it should look like this:

 editor.setRange(`${activeSheet+st}:${activeSheet+end}`);

3 You have an extra set of redundant parentheses at the very end:

          editor.setRange(`${activeSheet+st}:${activeSheet+end}`);
          webix.delay(() => editor.focus());
        }
        return false;
      };
    });
  }
});
}); <--

which seems like that was the thing that prevented you from running the code.

Here is the fixed snippet: https://snippet.webix.com/gkhgot32. Please tell me if that fixed it for you or you are still having issues.

I am not sure what is wrong here, I am using same code as yours now, still it’s not displaying me spreadsheet. no errors in console.

As soon as I remove just button code,rows: [
{
view: “button”, value: “Update”, width: 200
},
{
Spreadsheet is getting load.

Also, wanted to let you know that my team have purchased webix licence and I am using it. Is there anything to do with that?

Everything should be fine even then, this might have to do with your spreadsheet being initialized in a container:

      container: "webixsheetCx",

You can try removing the container (https://snippet.webix.com/dx0zczqh) and check the result or just move the button inside the toolbar as you can see here: https://snippet.webix.com/cq4woau3.