How can I extend sw-context-menu-item and use a custom config action route?
If i override sw-context-menu-item and there is another plugin that does that , it wont work.
Also tried to extend it with this but with no luck:
Component.extend('my-custom-extension', 'sw-context-menu-item', {
`<template>
<sw-context-menu-item
:icon="icon"
:label="label"
:disabled="disabled"
:routerLink="routerLink"
#click="onClick"
class="sw-context-menu-item"
/>
</template>`
});
Is there another way to change the plugin config to point to another route?
Overriding the original component, you could alter the routerLink object on creation.
Component.override('sw-context-menu-item', {
created() {
if (!this.routerLink || this.routerLink.name !== 'route.to.replace') {
return;
}
this.routerLink.name = 'new.route';
this.routerLink.params = {};
},
});
Related
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.
So, I have an MVC5 site that uses the default routing template {controller}/{action}/{id} and this works fine. Most everything in the site requires a login (i.e. [Authorize] attribute is used almost everywhere), and this works fine.
Well, now I have a need to allow anonymous access to select pages when a certain kind of link pattern is used: App/{token}/{action}. The {token} is a random string associated with something in my database. I can issue and deactivate these tokens at will.
I got this new App/{token}/{action} routing working by implementing a custom RouteBase that parses the incoming URL for these tokens, and, crucially, adds the the token value to the RouteData.DataTokens so that my App controller can make use of it without needing an explicit action argument for it. So, I added this new route to the route table ahead of the default routing like this:
// new route here
routes.Add("AppToken", new AnonAppAccessRoute());
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Here is the problem/question: adding this now route has now made my default route stop working -- everything is now going through AnonAppAccessRoute which of course is meant to work only for a few things. I don't understand how to make my AnonAppAccessRoute apply only to URLs with a certain pattern. The MapRoute method accepts a URL pattern, but Adding a route doesn't seem to let you put a filter on it. What am I missing? I've looked around quite a bit at various blogs and documentation about routing, but I've not found good info about using the DataTokens collection (which I feel is important to my approach), and I'm not seeing a good explanation of the difference between Adding a route explicitly vs calling MapRoute.
Here's the code of my custom RouteBase:
public class AnonAppAccessRoute : RouteBase
{
public override RouteData GetRouteData(HttpContextBase httpContext)
{
RouteData result = null;
string[] pathElements = httpContext.Request.Path.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
if (pathElements.Length > 0)
{
string token = TryGetArrayElement(pathElements, 1);
if (!string.IsNullOrEmpty(token))
{
result = new RouteData(this, new MvcRouteHandler());
result.DataTokens.Add("appToken", token);
result.Values.Add("controller", "App");
result.Values.Add("action", TryGetArrayElement(pathElements, 2, "Index"));
}
}
return result;
}
private string TryGetArrayElement(string[] array, int index, string defaultValue = null)
{
try
{
return array[index];
}
catch
{
return defaultValue;
}
}
public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
{
return null;
}
}
I got this to work by dropping the custom RouteBase and instead used this MapRoute call like this:
routes.MapRoute(
name: "AppAnon",
url: "App/{token}/{action}",
defaults: new { controller = "App", action = "Index" }
);
Then, in my App controller, I did this in the Initialize override:
protected AppToken _appToken = null;
protected override void Initialize(RequestContext requestContext)
{
base.Initialize(requestContext);
string token = requestContext.RouteData.Values["token"]?.ToString();
_appToken = Db.FindWhere<AppToken>("[Token]=#token", new { token });
if (!_appToken?.IsActive ?? false) throw new Exception("The token is not found or inactive.");
}
This way, my "token" is available to all controller actions via the _appToken variable, and already validated. I did not need to use RouteData.DataTokens. Note that my Db.FindWhere statement is ORM-specific and not really related to the question -- it's just how I look up a database record.
Is there a way to disable the jQuery Validation for a certain validator (creditcard) so that it only occurs onblur, instead of onkeyup?
Based on the jQuery Validator documentation I thought I could do something like this:
$(function () {
$("[data-val-creditcard]").validate({
onkeyup: false
})
});
However, it doesn't seem to be working.
I also tried doing the following on my validator:
public class CreditCardValidator : DataAnnotationsModelValidator<CreditCardAttribute>
{
string _message;
public CreditCardValidator(ModelMetadata metadata, ControllerContext context, CreditCardAttribute attribute)
: base(metadata, context, attribute)
{
_message = attribute.ErrorMessage;
}
public override IEnumerable<ModelClientValidationRule> GetClientValidationRules()
{
var rule = new ModelClientValidationRule
{
ErrorMessage = _message,
ValidationType = "creditcard"
};
rule.ValidationParameters.Add("onkeyup", false);
return new[] { rule };
}
}
It doesn't work either, but I was just taking a stab at the appropriate use of ValidationParameters.
It is kind of annoying to be entering a credit card number in a form and having it randomly change from invalid to valid, then back to invalid.
Any ideas? Thanks!
Ok guys,
I was in the same problem and found this thread: http://old.nabble.com/-validate--onkeyup-for-single-field-td21729097s27240.html
The idea is basically to overwrite the keyup event and return false. So in your specific case you'll need to add:
$('#my-form').validate({
rules: {
[...]
}
}
// Disable keyup validation for credit card field
$("[data-val-creditcard]").keyup(function() { return false } );
And you'll see that your credit card field is only checked on blur or submit (but the rest is working on keyup also).
I was looking for the same solution, and found that the answer here could be improved, so I thought it would be nice to share it here.
$.validator.setDefaults doesn't work for unobtrusive validation as the validator is initialized internally.
To change the settings on forms that use unobtrusive validation you can do the following:
var validator = $("form").data("validator");
if (validator) {
validator.settings.onkeyup = false; // disable validation on keyup
}
I realise this is an old post, but none of the responses appear to answer this question,
How to disable onkeyup and enable onblur?
I was looking for this so thought I would share the answer.
As Ben Foster rightly said, onkeyup can be disabled by doing the following
var validator = $("form").data("validator");
if (validator) {
validator.settings.onkeyup = false;
}
To enable validation onblur we can use onfocusout
validator.settings.onfocusout = function(element)
{
$(element).valid();
};
So our code to disable onkeyup and enable onblur look like this
var validator = $("form").data("validator");
if (validator)
{
validator.settings.onkeyup = false;
validator.settings.onfocusout = function(element)
{
$(element).valid();
};
}
Don't know how to set it to a specific field, but you could try this to disable keyup validation (for all fields):
$.validator.setDefaults({
onkeyup: false
})
See
MVC 3 specifying validation trigger for Remote validation
ASP.NET Remote Validation only on blur?
You could also use something like the above,
$("form").validate({
onfocusout: false,
onkeyup: false
});
In case you have custom rules then,
$("form").validate({
onfocusout: false,
onkeyup: false,
rules: {
"name1": {
required: true,
email: true,
maxlength: 100
},
"name2": {
required: true,
number: true
}
}
});
This answer in the jQuery forum helped me a lot.
You could set the defaults to off in the onfocus event of the credit field, then turn them in the onblur. Seems hacky, but could work.
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
});
}
}
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.