VueJS-3 How to access raw text of a v-model expression - vuejs3

For example if my HTML tag says <input v-model=“foo.bar”> I need the actual text foo.bar, rather than the object that foo.bar resolves to.
In Vue 2 my component was able to use this.$vnode.data.model.expression
What is the equivalent in Vue 3?

It's not documented, and kind of a hack, but I just solved it like this:
For v-model="foo.bar"
In vue2: node.$vnode.data.model.expression
In vue3: node.$attrs['onUpdate:modelValue'].toString() returns $event => ((_ctx.foo.bar) = $event), so you can get your foo.bar from there.

Related

Svelte: Web components passing prop camel case

I am using web components generated by svelte.
I have props defined in camel case (someType) and the expectation was that the following should work but doesn't
<my-web-c some-type="stringVal"></my-web-c>
Is this to be expected? Are there any options by which this can work?
I am aware that passing props as snake case and plain values does work like in JS (some_type)
<my-web-c some_type="stringVal"></my-web-c>
or in JS (sometype)
<my-web-c sometype="stringVal"></my-web-c>
But was curious about the camel case.
You can just use a camel case prop like this:
<my-web-c someType="stringVal"></my-web-c>
This REPL shows different props types in action. Kebab-case isn't currently supported. There is an issue open for it here.
Passing camel case prop just works only in svelte components. It doesn't work with custom elements.
You can use as below;
<my-web-c samplecomp = 'Sample Comp'></my-web-c>
<my-web-c sample_comp = 'Sample Comp'></my-web-c>

How do I make a node title translatable?

I'd like to translate each node title as a string (using i18n). I'm trying this function in my theme template:
function theme_process_page(&$variables) {
$variables['title'] = t($variables['title']);
}
Yet when I refresh strings, none of my node titles are on the list. Is there something I'm missing?
And to clarify the function name is using my theme name, not the word "theme".
Title is my usual solution for this (I use Entity Translation, it works fine with Title module).
This module replaces node titles by a regular translatable text field. You can choose wich content type titles must be replaced (on the "Manage Field" forms, you'll find a "replace" link in the title row). Pretty useful.
Good luck
You should never use t() to translate user-supplied or variable strings. See the documentation on the function.
That said, there are some solutions, one is to use the built-in language support for entity fields. Following that you should be able to do something like this in a field hook (in a module, not in your template):
$langcode = $field_info['translatable'] ? $content_langcode : LANGUAGE_NONE;
$entity->{$field_name}[$langcode][0]['value'] = t("Salut!");

Meteor how to save templates in mongo

I want to give my users the possibility to create document templates (contracts, emails, etc.)
The best option I figured out would be to store these document templates in mongo (maybe I'm wrong...)
I've been searching for a couple of hours now but I can't figure out how to render these document template with their data context.
Example:
Template stored in Mongo: "Dear {{firstname}}"
data context: {firstname: "Tom"}
On Tom's website, He should read: "Dear Tom"
How can I do this?
EDIT
After some researches, I discovered a package called spacebars-compiler that brings the option to compile to the client:
meteor add spacebars-compiler
I then tried something like this:
Template.doctypesList.rendered = ->
content = "<div>" + this.data.content + "</div>"
template = Spacebars.compile content
rendered = UI.dynamic(template,{name:"nicolas"})
UI.insert(rendered, $(this).closest(".widget-body"))
but it doesn't work.
the template gets compiled but then, I don't know how to interpret it with its data context and to send it back to the web page.
EDIT 2
I'm getting closer thanks to Tom.
This is what I did:
Template.doctypesList.rendered = ->
content = this.data.content
console.log content
templateName = "template_#{this.data._id}"
Template.__define__(templateName, () -> content)
rendered = UI.renderWithData(eval("Template.#{templateName}"),{name:"nicolas"})
UI.insert(rendered, $("#content_" + this.data._id).get(0))
This works excepted the fact that the name is not injected into the template. UI.renderWithData renders the template but without the data context...
The thing your are missing is the call to (undocumented!) Template.__define__ which requires the template name (pick something unique and clever) as the first argument and the render function which you get from your space bars compiler. When it is done you can use {{> UI.dynamic}} as #Slava suggested.
There is also another way to do it, by using UI.Component API, but I guess it's pretty unstable at the moment, so maybe I will skip this, at least for now.
Use UI.dynamic: https://www.discovermeteor.com/blog/blaze-dynamic-template-includes/
It is fairly new and didn't make its way to docs for some reason.
There are few ways to achieve what you want, but I would do it like this:
You're probably already using underscore.js, if not Meteor has core package for it.
You could use underscore templates (http://underscorejs.org/#template) like this:
var templateString = 'Dear <%= firstname %>'
and later compile it using
_.template(templateString, {firstname: "Tom"})
to get Dear Tom.
Of course you can store templateString in MongoDB in the meantime.
You can set delimiters to whatever you want, <%= %> is just the default.
Compiled template is essentially htmljs notation Meteor uses (or so I suppose) and it uses Template.template_name.lookup to render correct data. Check in console if Template.template_name.lookup("data_helper")() returns the correct data.
I recently had to solve this exact (or similar) problem of compiling templates client side. You need to make sure the order of things is like this:
Compiled template is present on client
Template data is present (verify with Template.template_name.lookup("data_name")() )
Render the template on page now
To compile the template, as #apendua have suggested, use (this is how I use it and it works for me)
Template.__define__(name, eval(Spacebars.compile(
newHtml, {
isTemplate: true,
sourceName: 'Template "' + name + '"'
}
)));
After this you need to make sure the data you want to render in template is available before you actually render the template on page. This is what I use for rendering template on page:
UI.DomRange.insert(UI.render(Template.template_name).dom, document.body);
Although my use case for rendering templates client side is somewhat different (my task was to live update the changed template overriding meteor's hot code push), but this worked best among different methods of rendering the template.
You can check my very early stage package which does this here: https://github.com/channikhabra/meteor-live-update/blob/master/js/live-update.js
I am fairly new to real-world programming so my code might be ugly, but may be it'll give you some pointers to solve your problem. (If you find me doing something stupid in there, or see something which is better done some other way, please feel free to drop a comment. That's the only way I get feedback for improvement as I am new and essentially code alone sitting in my dark corner).

Meteor handlebars {{#if}} turns strings into objects

The bug source code is here.
Let's say I'm looping over an array in Meteor using an ordinary {{#each}} loop. Each array element is a string, and I output the string every step using {{this}}. So far so good! If I use a handlebars helper to check typeof for this I'll get string. Sweet! Everything is as it should be.
But if I add an {{#if something }}-helper inside the {{#each}} (the something just returns true and thus keeps going and outputs {{this}}) the string will still look good in the HTML, but it is now an object in the typeof check!
This is super-annoying as all the (typeof someVarINeedToTest === 'string') my code might depend on now will return false.
Am I doing something wrong?
Or is this an actual bug?
If so: is it a Meteor-specific or Handlebars-specific bug?
Thanks!
Oh: the source link again. Just pull and run meteor and look in your browser console.
This is because the this variable is supposed to always be an object in JavaScript so when someFunction.apply(someContext); is called in by handlebars, JavaScript turns someContext into an object no matter what it started as. See an example here: http://jsfiddle.net/SyKSE/1/
(In this case, someFunction represents the part of your template that's within the {{#if}} statement.)
A simple (albeit ugly) workaround would be to just always pass your data in as an object, so
['this', 'is', 'an', 'array', 'that', 'we\'re', 'looping', 'through'];
becomes:
[{val: 'this'}, {val: 'is'}, {val: 'an'}, {val: 'array'}, {val: 'that'}, {val: 'we\'re'}, {val: 'looping'}, {val: 'through'}];
And then you'd change your template to look at val instead of this

Pass field content as variable from block preprocessor to block tpl

I have a preprocess function:
[MYTHEMENAME]_theme_preprocess_views_view_fields__random_quote__block(&$vars)
and then a template file to render the variables:
views-view--random_quote--block.tpl.php
I can easily set a variable like so:
$vars['bam'] = 'whatever';
and display that in my template file. Now my question is, how do I pass the contents of a field to my template? Something like:
$vars['customer_name'] = 'field_customer_name';
Where 'field_customer_name' is a field in the content type. I have tried using the field api and I am getting nowhere. My view is getting that field and I can see the data in the preview of the view content
I still haven't figure out how to do this, but I ended up using a fields tpl (in this case: views-view-fields--random_quote.tpl.php) so I could format each field like so
<cite><b><?php print strip_tags($fields['field_customer_name']->content); ?></b>
Ok, I figured out how to do it!
$entity = $vars['view']->result[0]->_field_data['nid']['entity'];
$vars['customer_name'] = '$entity->field_customer_name[$entity->language][0]['value'];
Hope this helps someone

Resources