From the docs, I can have multiple v-model bindings by doing this:
<script setup>
defineProps({
firstName: String,
lastName: String
})
defineEmits(['update:firstName', 'update:lastName']) // array syntax
</script>
However, I would like to validate my events with the object syntax instead of the array syntax shown here.
But the name has the update: prefix, the colon doesn't allow me to use the object syntax. Is there another way to go about achieving that?
The keys in object syntax can be strings.
The following should work:
defineEmits({
'update:firstName': (val: string) => true,
'update:lastName': (val:string) => true,
})
Related
I have this type:
export interface ConnectorForModel {
_type: "connector.for.model",
connectorDefinitionId: string
}
I want to model is as a zod schema. Actually I am using toZod, like this:
export const ConnectorForModelZod: toZod<ConnectorForModel> = z.object({
_type: z.literal("connector.for.model"),
connectorDefinitionId: z.string()
});
And I get this type error:
Type 'ZodLiteral<"connector.for.model">' is not assignable to type 'never'.
Whats the right way to express this?
I think the quickest way to get this working is with ZodType:
import { z } from "zod";
export interface ConnectorForModel {
_type: "connector.for.model";
connectorDefinitionId: string;
}
export const ConnectorForModelZod: z.ZodType<ConnectorForModel> = z.object({
_type: z.literal("connector.for.model"),
connectorDefinitionId: z.string()
});
Aside: I tend to define my types from my zod schemas rather than the other way around. If you don't have control over the type that you're working with then the given approach is the way to go, but you could potentially avoid writing the same code twice using z.TypeOf on the zod schema
type ConnectorForModel = z.TypeOf<typeof ConnectorForModelZod>;
This type would be equivalent to your interface.
I am trying to implement redux-query-sync but the url keeps going to default state if I share the url which has the updated state.
https://github.com/Treora/redux-query-sync/blob/master/src/redux-query-sync.js
I have implemented as shown in the sample - https://codesandbox.io/s/url-query-sync-qjt5f?from-embed=&file=/src/index.js
There is also a PropsRoute implementation in the code.
Your example seems to be working for the string arguments. It's the array param selected which is giving you trouble.
The action creator that you are dispatching here, changeLocation, does not take the right arguments. Look at how you are calling it in your component:
changeLocation({
location: event.target.name,
checked: event.target.checked
});
When it is called from the URL query it is going to be called like:
changeLocation([Stockholm, Oslo]);
So obviously these do not match up. The existing changeLocation action can only handle one location at a time, so there's not a way to map the value from the URL to a payload that you can use with it. You will need to create a separate action.
const setLocation = (payload) => ({ type: "setLocation", payload });
case "setLocation":
return {...state, selected: payload};
My first approach to handle the array values was to implement the optional stringToValue and valueToString settings for the selected param.
This only kinda-sorta works. I can't get it to omit the param from the URL when it is set to the default value. I wonder if it's using a === check? As a hacky solution, I added a filter in the stringToValue to prevent the empty string from getting added to the locations array. But the selected= is always present in the URL.
selected: {
selector: (state) => state.selected,
action: setLocation,
stringToValue: (string) => string.split(",").filter(s => !!s),
valueToString: (value) => value.join(","),
defaultValue: []
}
This really annoyed me, so I followed this bit of advice from the docs:
Note you could equally well put the conversion to and from the string in the selector and action creator, respectively. The defaultValue should then of course be a string too.
And this approach worked much better.
selected: {
selector: (state) => state.selected.join(","),
action: (string) => setLocation(string.split(",")),
defaultValue: ""
}
With those changes you should have a shareable URL.
Forked Sandbox
Thanks Linda. The example I sent was what I referred to do my implementation. It wasn't my work.
Just letting you know that since my app uses PropsRoute I was able to use history props to push the state as params in url and share the url. I had to modify code to use params from url as state if it was available. This worked between tabs. Will be testing across machines.
this.props.history.push("/currenturl/" + state)
this.props.history.push("/currenturl/" + {testobject:{}})
this.props.match.params.testobject
wasn't able to implement redux-query-sync though.
I tried the following code to pass data to a template and receive it in onCreated() but I cannot access the data.
deviceInfo.js:
BlazeLayout.render('layout',{main:'deviceInfo',stats:'paramstats',attr:"SOME_DATA"});
deviceInfo.html:
{{>Template.dynamic template=stats data=attr}}
paramstats.js:
Template.paramstats.onCreated( () => {
console.log("onCreated");
console.log("Data is:",this.data.attr);
});
But I get TypeError: Cannot read property 'attr' of undefined.
where am I going wrong?
You need to use the normal function syntax for onCreated callback. Arrow function will bind the context of your function to the outer scope automatically, it is the cause of your problem. Try this:
Template.paramstats.onCreated(function() {
console.log("onCreated");
console.log("Data is:",this.data.attr);
});
I am using Meteor 1.4.# and I was able to retrieve the parameters like so:
BlazeLayout.render("page", {
params: ['fullscreen', 'route']
});
// page.js
Template.page.onCreated(function() {
let params = this.data.params();
console.log(params);
}
Not quite sure why you're using two levels of indirection. BlazeLayout.render() is giving you one level and then you're using a dynamic template within that? Why not directly render the template you ultimately want using BlazeLayout.render()?
In any case, you're dereferencing your data context indirectly.
In the BlazeLayout.render() call you're setting the attr variable to some value.
Then in your dynamic template you're using data=attr but this means that inside your template helpers that this is going be have the value of attr. There will be no data subkey added automatically.
You don't show the value that you're setting for attr so it's not even clear that you have an attr subkey in your attr variable, that would also be confusing to anyone else who ever tries to debug your code.
#khang is correct about not using the arrow function syntax in onCreated(), try:
Template.paramstats.onCreated(function(){
console.log("onCreated");
console.log("Data is:",this);
});
this should have whatever value you stuffed into attr in your BlazeLayout.render()
I am trying to find a way to pass a string variable (coming from a dictionary) into my website's data layer.
My array is built using the following snippet:
[{foreach from=$orderArticles item="currOrderArticle"}]
[{assign var="currBasePrice2" value=$currOrderArticle-getBasePrice()}]
product_list.push(
{
id: "[{$currOrderArticle-oxorderarticles__oxartnum->value}]",
price: [{$currBasePrice2->getBruttoPrice()}],
quantity: [{$currOrderArticle-oxorderarticles__oxamount->value}]
}
);
products_info.push(
{
transaction_id: '[{$order->oxorder__oxordernr-value}]',
transaction_cid: '[{$order->oxorder__oxuserid-value}]',
item_id: '[{$currOrderArticle-oxorderarticles__oxartnum->value}]',
item_value: '[{$basket-getDiscountedNettoPrice()}]',
item_quantity: '[{$currOrderArticle-oxorderarticles__oxamount->value}]'
}
);
[{/foreach}]
If I want to pass it to the data layer, I do the following:
dataLayer.push({
ProductsInfo: products_info
});
This works fine, the issue is that I actually want to modify this array.
I would like to apply the following to it before passing it into the data layer:
products_info|json_encode|escape:'url'
But when I try to do it during the push, it does not work:
dataLayer.push({
ProductsInfo: products_info|json_encode|escape:'url'
});
As I told you in another post, Smarty expressions must be enclosed in delimiters, in your case [{ and }]
Also, as you're using the string in javascript, it must be enclosed within quotes:
dataLayer.push({
ProductsInfo: '[{products_info|json_encode|escape:'url'}]'
});
So up until this point my experience with Collection2/Simple Schema has been basic at best. Now, I'm trying to validate values for 'types' based on documents in a Type collection.
#Data = new Mongo.Collection 'data'
Data.attachSchema new SimpleSchema
'types':
'type': [String]
'label': 'Types'
'custom': ->
if #isSet
Meteor.call 'isType', #value, (error, result) ->
if !result
Data.simpleSchema().namedContext('admin_update').addInvalidKeys [
'name': 'types'
'type': 'notAllowed'
]
'otherField':
'type': Number
'label': 'Other Field'
'optional': true
So far, my isType Method has been validating the values correctly, but regardless of whether it returns true or false, it stores the value anyway (even though the form flashes the error message briefly). I don't think I grasp custom validation well enough to figure out how to do this correctly, so any and all help would be appreciated, even if it's just pushing me in the right direction.
You can use the allowedValues field, which can take an array or a function. Use a function.
MyCollection.attachSchema(new SimpleSchema({
types: {
type: [String],
allowedValues: function () {
// assuming "Types" is the collection.
return Types.find().map(function (doc) {
return doc._id;
});
}
}
}));
This validates on the back end so the publications and subscriptions will not be a problem.