Very new to Ember, quick question please: How do I save/persist a change to an attribute? Have the following action in the controller:
actions: {
togOnField: function(){
if (this.get('onField')){
this.set('onField', false);
} else {
this.set('onField', true);
}
}
}
Looking around I've found
this.get('model').save
At the moment, using this, the attribute is immediately reverting back to its previous state. Does this mean the save is unsuccessful? Working with a Sails API and Postgres DB, both seem to be working fine.
And what are the different options for how I might save from this action? Thanks a lot.
this in that controller refers to the controller, probably not the model as you expect. One thing you can do is pass in the model to the action.
In your template,
<button {{action 'toggleOnField' user}}>Toggle on field</button>
Then the action becomes
actions: {
toggleOnField: function(user) {
user.toggleProperty('onField').save().then(function() {
// do something
}, function(reason) {
// handle error
});
}
}
Related
I want to handle my own undo/redo menu commands and at the same time still support the Electron built-in undo/redo of the webContents object when it is relevant, for example when the user is focused on a text input element.
This answer seems like a good start, but it is incomplete as it does not address the root question, which is how to mix the two things.
Here is how the ideal code would look like when defining the menu item:
{
label: 'Undo',
accelerator: 'CmdOrCtrl+Z',
click: function(menuItem, focusedWin) {
if (*** focusedWin.webContents thinks it can handle it ***) {
focusedWin.webContents.undo();
} else {
// Run my own code
}
}
}
The one dollar question is: how do I code the "if focusedWin.webContents thinks it can handle it" test?
I found a solution to my problem. It's not elegant, but it works. The idea is that the built-in Edit menus such as undo/redo/cut/copy/paste/delete/etc. should be managed by the webContents object only when the user is focused on an input or textarea element.
So in my index.html file, I send a message to the Main process when there is a focus or a blur event on input elements. This sets a global variable (yuck!) on the main process side which is used to make the decision between letting webContents do its job or doing it ourselves.
In index.html (I use jQuery and the great messaging system described in this other thread):
//-- Tell the main process if the preset Edit menus should be activated or not.
// Typically we active it only when the active item has text input
$('input').focus(() => window.api.send("menus:edit-buildin", { turnItOn: true }));
$('input').blur(() => window.api.send("menus:edit-buildin", { turnItOn: false }));
In main.js:
// This is a global :-( to track if we should enable and use
// the preset Edit menus: undo/redo/cut/copy/paste/delete
var menusEditPreset = false;
// Listen to the renderer
ipcMain.on("menus:edit-buildin", (event, { turnItOn }) => {
menusEditPreset = turnItOn;
});
// ... and in the menu definition:
{
id: 'undo',
label: 'Undo',
accelerator: 'CmdOrCtrl+Z',
click: (event, focusedWindow, focusedWebContents) => {
if (menusEditPreset) {
focusedWindow.webContents.undo();
} else {
console.log("My own undo !");
}
}
},
There is a view OrderWizard module view in suitecommerce core code.It has methods similar to below(not the exact code, not pasting for proprietary issues).
I have created the extension and calling OrderWizard's method from the extension.
**setAddr: function(xxx, xxxx) {
this.model.setAddress(xxx, xxxx, xxxx);
return this;
}
renderView: function() {
if (!this.isActiveVal()) {
return this;
}
}**
Extension class:
**define(
'TEST.PaymentValidation.PaymentValidation'
, [
'OrderWizard.xxxxx.xxxxx'
]
, function (
OrderWizardAddress
)
{
'use strict';
return {
mountToApp: function mountToApp (container)
{
_.extend(OrderWizardAddress.prototype,
{
setAddressExt: function setAddressExt() {
{
OrderWizardAddress.prototype.setAddr.apply(this, arguments);
}
}
});
_.extend(OrderWizardAddress.prototype,
{
renderExt: function renderExt() {
{
OrderWizardAddress.prototype.renderView.apply(this, arguments);
}
}
});
OrderWizardAddress.prototype.setAddressExt();
OrderWizardAddress.prototype.renderExt();
}
};
});**
when calling the renderExt method,
Cannot read property 'isActiveVal' of undefined TypeError: Cannot read property 'isActiveVal' of undefined. Eventhough isActiveVal is available in OrderWizard view.
When calling the setAddressExt
I'm getting 'this is undefined'.
Can someone help me what I'm doing wrong here. What is the best way to call the suitecommerce core codes method from the extension.I guess I'm not passing the actual context(.apply(this) of the OrderWizard view.
Figured out the solution.Basically two independent views have to communicate among each other and display the value.
Payment view and Billing view are two different views. Based on the payment method selected, default billing address needs to selected.Used Backbone's event queue aggregator approach to solve this problem. when the payment method is selected, a publisher sends a message to subscriber. If the payments method is Invoice, publisher publishes the message to subscriber which triggers a method to select the default Billing address.
To add new method from the extension, used the javascript prototype and to add codes to the existing method, used the underscore's wrap method
I am trying to create an action that loads a view dynamically based on param passed in url
below is my routes.js
'GET faq/:alias': {actions:'faq'}
in my faq action
module.exports = {
friendlyName: 'FAQ Pages',
inputs: {
alias: {
description: 'the page url',
type: 'string'
}
},
exits: {
success: {
statusCode: 200,
},
notFound: {
responseType: 'notFound',
}
},
fn: async function(inputs, exits) {
console.log('static', inputs.alias);
//something like this - set view tempalatePath
//exits.success.viewTemplatePath = 'faqs/' + inputs.alias;
//load view if exist else throw notFound
return exits.success();
}
};
All my faq's are in a folder, I will check if the physical file exists using require('fs').existsSync() and then load load it
In the action2 format which you are using, you have to use throw to route to an alternate exit. See:
https://sailsjs.com/documentation/concepts/actions-and-controllers
Do not be confused by the documentation here:
https://sailsjs.com/documentation/reference/response-res/res-view
... I don't know what it applies to, but it doesn't apply to action2's in 1.0.
This took me a while to figure out too, but below is best way I found to work. In your faq action, change:
return exits.success();
to this:
return this.res.redirect('faq/' + inputs.alias);
BACKGROUND:
I notice in sails.js action2, when you use 'exits' where success responseType is defined as a 'view', it will not use the view-faq.js file at all, just skips directly to the faq.ejs page. I'm using responseType 'redirect' to go to the view-faq.js first before loading the page.
If you do use responseType 'view' in your exits.success, you would need to add into your action the same code from fn: in your faq.js, and also send the page locals. The problem I found with this method was an issue where the 'me' local somehow wasn't functioning properly with the new page view, which messed up my particular template.
Hope this saves someone else hours of time.
There are only four methods for chrome.contextMenus:
create
update
remove
removeAll
I am wondering how do I check whether one menu is already created?
I tried this:
try {
chrome.contextMenus.update("byname", {});
} catch (e) {
// doesn't exist
}
But it seems the error cannot be caught (but shown in the console).
Thanks for any kind of tips!
Each chrome.contextMenus.create call returns an unique identifier. Store these identifiers in an array or hash to keep track of them.
This is a direct solution to anyone having the op's problem, based on the suggestion by Rob W. The idea is to maintain your own list of existing context menu id's.
By using these wrapper functions to maintain context menu entries, also the removal and updates are being kept track of (addressing Fuzzyma's comment).
Usage works like Chrome's own methods, eg. createContextMenu({id: "something"}, onclick). It works for me.
let contextMenus = {}
// method to create context menu and keep track of its existence
function createContextMenu() {
if (arguments[0] && arguments[0].id) {
// TODO: not sure if this will work properly, is creation synchronous or asynchrounous?
// take in to account calll back and the runtime error?
chrome.contextMenus[arguments[0].id] = chrome.contextMenus.create.apply(null, arguments);
}
}
function updateContextMenu() {
if (arguments[0] && contextMenus[arguments[0]]) {
chrome.contextMenus.update.apply(mull, arguments);
}
}
function removeContextMenu() {
if (arguments[0] && contextMenus[arguments[0]]) {
chrome.contextMenus.remove.apply(null, arguments);
contextMenus[arguments[0]] = undefined;
}
}
function contextMenuExists(id) {
return !!contextMenus[id];
}
I have been looking at the Todo list example (source) for Backbone.js. The code uses local storage, and I wanted to try and convert it so that it operated via a RESTful webservice.
Suppose the webservice already exists at the route todos/. I figured I need to add in a url piece into Backbone.Model.extend and remove the localStorage: new Store("todos") line when we perform Backbone.collection.extend.
window.Todo = Backbone.Model.extend({
url : function() {
return 'todos/'+this.id;
}
// Default attributes for a todo item.
defaults: function() {
return {
done: false,
order: Todos.nextOrder()
};
},
// Toggle the `done` state of this todo item.
toggle: function() {
this.save({done: !this.get("done")});
}
});
What is the proper way to do this?
Url should be set in Collection, if you have need for diferent urls than those created by collection than declare url in model.
You need to remove
<script src="../backbone-localstorage.js"></script>
from index.html since it is linked after backbone.js and effectively overrides Backbone's sync method to store in localStorage.
I would leave the model as it is in the Todos example. In the collection class add this property:
window.TodoList = Backbone.Collection.extend({
...
url: '/todos',
...
}
Calling fetch() on the collection should retrieve a list of Todo objects.
If you are using Rails you need to set ActiveRecord::Base.include_root_in_json = false otherwise Backbone.js will not be able to pull out the Todo objects from the returned json.