"TypeError: this.types is not a function" when using "vuex-orm-decorators" - vuex-orm

I'm trying to use the npm package 'vuex-orm-decorators' from https://github.com/scotley/vuex-orm-decorators#readme
When I try to insert into the DB, I get the error TypeError: this.types is not a function
Entity looks like this
import { Model } from "#vuex-orm/core";
import { NumberField, OrmModel, StringField } from "vuex-orm-decorators";
#OrmModel("races")
export default class Race extends Model {
#NumberField()
public ID!: number;
#StringField()
public Name!: string;
}
store looks like this:
import Vue from "vue";
import Vuex from "vuex";
import { ORMDatabase } from "vuex-orm-decorators";
Vue.use(Vuex);
export default new Vuex.Store({
.
.
.
plugins: [ORMDatabase.install()]
});
Also, maybe this is a clue.... in Vuex-Orm, this.setters is returning a value, but this.setters('all') is returning undefined.
/**
* Get all records.
*/
Model.all = function () {
return this.getters('all')();
};
From seeing the undefined basic fields and functions, it seems like the vuex-orm database isn't getting set up correctly. Any ideas?
I tried to create a stackoverflow tag for vuex-orm-decorators, but I'm not quite at 1500 rep yet, so I just tagged it as vuex-orm.

There is a small bug in vuex-orm-decorators package in the implementation of the types function defined in Vuex-ORM Single Table Inheritance docs.
I've created a fork in which I fixed this simple problem and created a pull request to update the original package.
Lastly, I've to point that from my tiny dive into this package that it isn't fully ready yet for table inheritance features built in Vuex-ORM but still is great for simple use cases.

Related

How to get Json Api rendering to work with json views in Grails v3.3.3

I have a simple problem and documentation is not helping me resolve it.
I have created a Grails v3.3.3 demo project - and created a simple domain class called JsonApiBook, with 'name' attribute like this
package ttrestapi
import grails.rest.*
#Resource (uri='/jsonApiBook', formats=['json','xml'])
class JsonApiBook {
static constraints = {
}
String name
}
and marked up the URI as the documentation says the JSON API rendering only works with domain classes (and not a controller class).
In my bootstrap I have saved a instance of book to the tables - and can view that generally.
In my views directory I have a created jsonApiBook folder and created two gson files.
A '_jsonApIBook' template like this
import ttrestapi.JsonApiBook
model {
JsonApiBook book
}
json jsonapi.render(book)
which invokes the jsonapi helper object to render the instance.
I have in the same directory created an index.json like this:
import ttrestapi.Book
model {
List<Book> bookList
}
// We can use template namespace
// method with a Collection.
json tmpl.book(bookList)
When I run the app and use postman or browser to render then I get a result but its Json api compliant (I think it's ignored the template).
So localhost:8080/jsonApiBook just returns (looks default layout):
[
{
"id": 1,
"name": "json api book3"
}
]
and localhost:8080/jsonApiBook/1 just returns 'null' which can't be right.
How should I be setting up the json views for rendering JSON API compliant output? As this doesn't appear to work correctly.
build.gradle
buildscript {
....
dependencies {
........
classpath "org.grails.plugins:views-gradle:1.2.7"
}
}
--
apply plugin: "org.grails.grails-web"
apply plugin: "org.grails.plugins.views-json"
dependencies {
. . .
compile "org.grails.plugins:views-json:1.2.7"
. . .
}
Domain JsonApiBook.groovy
import grails.rest.Resource
#Resource (uri='/jsonApiBook', formats=['json','xml'])
class JsonApiBook {
String name
static constraints = {
}
}
Bootstrap.groovy
class BootStrap {
def init = { servletContext ->
new JsonApiBook(name: 'first').save(flush:true)
new JsonApiBook(name: 'second').save(flush:true)
new JsonApiBook(name: 'third').save(flush:true)
new JsonApiBook(name: 'fourth').save(flush:true)
new JsonApiBook(name: 'fifth').save(flush:true)
}
def destroy = {
}
}
Created folder under view called jsonApiBook
Created template named _jsonApiBook.gson in jsonApiBook folder
model {
JsonApiBook jsonApiBook
}
json {
name jsonApiBook.name
}
created show.gson under same folder
model {
JsonApiBook jsonApiBook
}
json g.render(template:"jsonApiBook", model:[jsonApiBook:jsonApiBook])
When i run http://localhost:8080/jsonApiBook i get bellow:
When i run http://localhost:8080/jsonApiBook/1 i get bellow:
Note: I used grails 3.3.3 with h2 memory DB
Reference
Hope this helps you
ok - got to similar place today on the train. Essentially the convention over configuration is core to whats happening here.
First the #Resource annotation generates a default RestfulController for you. In this approach the default base template _resourceClassName.gson expects the model variable to have the same name as the resource type so my original example instead of 'book'
import ttrestapi.JsonApiBook
model {
JsonApiBook book
}
json jsonapi.render(book)
it should really read as (following convention)
import ttrestapi.JsonApiBook
// variable should be same name as the Class name starting with lowercase
// as default (it can be different but the caller has to change how the
// the template parameter is invoked
model {
JsonApiBook jsonApiBook
}
json jsonapi.render(jsonApiBook)
Then the index.gson should have read as modified below
import ttrestapi.JsonBookApi
//note although not obvious in the written docs which use the show command, the
// default expected model variable is <resourceClass>List
model {
List<JsonBookApi> jsonBookApiList
}
// We can use template namespace
// method with a Collection.
json tmpl.jsonBookApi (jsonBookApiList )
If you want to use another variable name then in the base template you'd have to declare that name as map when calling the base template, from the index.gson . e.g. say the variable name in the base template was
model {
JsonBookApi myBook...
then when calling this template from my index.gson you would put something like this
...
model {
List<JsonBookApi> jsonBookApiList
}
json tmpl.jsonBookApi ("myBook", jsonBookApiList )
this invokes the correct template _jsonBookApi, but takes the model variable default in the index.gson and forces it to bind the value of jsonBookApiList to the myBook variable in the base template (_jsonBookApi.gson).
With the default generation of a controller, using #Resource annotation, the model variable will always be 'resourceClassName'List
I think the only way to change that is not to use the #Resource annotation on your domain class, but to use the URL mappings configuration to map your uri to a controller, and then you have to create a controller yourself by hand and ensure you extend from RestfulController. doing this you can override the default model variable name by implementing an overidden 'index()' method and ensuring you explicitly name the model variable you want, and ensure that the index.gson model variable is exactly the same as that set in your controller.
however the key point was I was not following the core convention defaults so the code as originally built couldn't work and returned null.
when you start out the documentation isn't absolutely clear what bits are part of the convention, and in the examples (which use show.gson) don't tell you what the model variable default name will be for the index.gson (add List to end) so its quite easy to get lost

TYPO3 extension "news": Custom fields on Fluid Template

I am using the extension News System, "news", and while changing the templates, I've noticed that while I can use things like {newsItem.datetime} or {newsItem.uid}, I cant use this with the custom fields i have created when extending the table tx_news_domain_model_news, like {newsItem.mycustomfield}
Edit: I have been pointed to this url and I've followed the instructions, but it's not working. This is my code
News.php
<?php
class Tx_WedoExtendnews_Domain_Model_News extends Tx_News_Domain_Model_News {
/**
* #var string
*/
protected $txWedoextendnewsLocation;
public function getTxWedoextendnewsLocation() {
return "this";
return $this->txWedoextendnewsLocation;
}
public function getWedoextendnewsLocation() {
return "that";
return $this->txWedoextendnewsLocation;
}
}
?>
Since I wasn't getting anything, I changed the returning values to string literals, to see if the problem was in the class and method names, or the property. Im still not getting anything. I think the underscored might be playing tricks on my code.
My extension key is wedo_extendnews and the new field is tx_wedoextendnews_location. Any ideas where the error lies?
Yes. To be able to access an object in fluid, you need the according setters in your model and maybe (not sure right now) an entry in the TCA.
If you want to access {newsItem.mycustomfield} you need an according setter in the model, like public function getMycustomfield() (note the get in get<Myfuncname>, it is mandatory).

MVCForm Agile Toolkit Form Update Record ID must be specified

hopefully simple questions regarding Agle Toolkit. Currently with the below code getting
Error in AJAX response: SyntaxError: Unexpected token <
BaseException
Record ID must be specified, otherwise use loadAny()
page\grant.php
<?php
class page_grant extends Page {
function init(){
parent::init();
$saveForm=$this->add('MVCForm');
$model=$this->add('Model_Grant')->load($_GET['id']);
$saveForm->setModel($model);
$saveForm->addSubmit();
$saveForm->onSubmit(function($saveForm){
$saveForm->update()->js()->univ()->successMessage('Grant info saved.')->execute();
});
}
}
And Model_Grant:
<?php
class Model_Grant extends Model_Table {
public $table='minigrant';
function init() {
parent::init();
$this->addField('grant_number');
$this->addField('grant_name');
$this->addField('uid');
}
}
Data is loaded fine but cannot save it back as per above error message.
You have to add the stickyGET to the id field:
<?php
class page_grant extends Page {
function init(){
parent::init();
$this->api->stickyGET('id');
$saveForm=$this->add('MVCForm');
$model=$this->add('Model_Grant')->load($_GET['id']);
$saveForm->setModel($model);
$saveForm->addSubmit();
$saveForm->onSubmit(function($saveForm){
$saveForm->update()->js()->univ()->successMessage('Grant info saved.')->execute();
});
}
}
Found data on:
http://agiletoolkit.org/learn/tutorial/jobeet/day8
Agile Toolkit really needs ONE documentation source with more examples like this because it is easily on the best frameworks I have worked with.
If they (#romaninsh) can do the documentation better then I think It would do better. I imagine they probably need to change the licence from AGPL too but that one matters less to me personally since I am working on OSS.

How to create a custom 404 page handler with Play 2.0?

What’s the preferred way to handle 404 errors with Play 2.0 and show a nice templated view?
You can override the onHandlerNotFound method on your Global object, e.g.:
object Global extends GlobalSettings {
override def onHandlerNotFound(request: RequestHeader): Result = {
NotFound(views.html.notFound(request))
}
}
Please note that there are really two different problems to solve:
Showing a custom 404 page when there is "no handler found", e.g. when the user goes to an invalid URL, and
Showing a custom 404 (NotFound) page as a valid outcome of an existing handler.
I think the OP was referring to #2 but answers referred to #1.
"No Handler Found" Scenario
In the first scenario, for "no handler found" (i.e. invalid URL), the other answers have it right but to be more detailed, per the Play 2.1 documentation as:
Step 1: add a custom Global object:
import play.api._
import play.api.mvc._
import play.api.mvc.Results._
object Global extends GlobalSettings {
override def onHandlerNotFound(request: RequestHeader): Result = {
NotFound(
views.html.notFoundPage(request.path)
)
}
}
Step 2: add the template. Here's mine:
#(path: String)
<html>
<body>
<h1>Uh-oh. That wasn't found.</h1>
<p>#path</p>
</body>
</html>
Step 3: tweak your conf/application.conf to refer to your new "Global". I put it in the controllers package but it doesn't have to be:
...
application.global=controllers.Global
Step 4: restart and go to an invalid URL.
"Real Handler can't find object" Scenario
In the second scenario an existing handler wants to show a custom 404. For example, the user asked for object "1234" but no such object exists. The good news is that doing this is deceptively easy:
Instead of Ok(), surround your response with NotFound()
For example:
object FruitController extends Controller {
def showFruit(uuidString: String) = Action {
Fruits.find(uuidString) match {
case Some(fruit) => Ok(views.html.showFruit(fruit))
// NOTE THE USE OF "NotFound" BELOW!
case None => NotFound(views.html.noSuchFruit(s"No such fruit: $uuidString"))
}
}
}
What I like about this is the clean separation of the status code (200 vs 404) from the HTML returned (showFruit vs noSuchFruit).
HTH
Andrew
If you want to do the same using Java instead of Scala you can do it in this way (this works for play framework 2.0.3):
Global.java:
import play.GlobalSettings;
import play.mvc.Result;
import play.mvc.Results;
import play.mvc.Http.RequestHeader;
public class Global extends GlobalSettings {
#Override
public Result onHandlerNotFound(RequestHeader request) {
return Results.notFound(views.html.error404.render());
}
}
Asumming that your 404 error template is views.html.error404 (i.e. views/error404.scala.html).
Please note that Play development team are making lots of efforts to move away from global state in Play, and hence GlobalSettings and the application Global object have been deprecated since version 2.4.
HttpErrorHandler.onClientError should be used instead of
GlobalSettings.onHandlerNotFound. Basically create a class that inherits from HttpErrorHandler, and provide an implementation for onClientError method.
In order to find out type of error (404 in your case) you need to read status code, which is passed as a one of the method arguments e.g.
if(statusCode == play.mvc.Http.Status.NOT_FOUND) {
// your code to handle 'page not found' situation
// e.g. return custom implementation of 404 page
}
In order to let Play know what handler to use, you can place your error handler in the root package or configure it in application.conf using play.http.errorHandler configuration key e.g.
play.http.errorHandler = "my.library.MyErrorHandler"
You can find more details on handling errors here: for Scala or Java.
This works in 2.2.1. In Global.java:
public Promise<SimpleResult> onHandlerNotFound(RequestHeader request) {
return Promise.<SimpleResult>pure(notFound(
views.html.throw404.render()
));
}
Ensure that you have a view called /views/throw404.scala.html
This works in 2.2.3 Play - Java
public Promise<SimpleResult> onHandlerNotFound(RequestHeader request) {
return Promise<SimpleResult>pure(Results.notFound(views.html.notFound404.render()));
}
html should be within /views/notFound404.scala.html
Dont forget to add Results.notFounf() and import play.mvc.Results;
For Java, if you want to just redirect to main page, I solved it by this.
#Override
public Promise<Result> onHandlerNotFound(RequestHeader request) {
return Promise.pure(redirect("/"));
}

MEF: how to import from an exported object?

I have created a MEF plugin control that I import into my app. Now, I want the plugin to be able to import parts from the app. I can't figure how setup the catalog in the plugin, so that it can find the exports from the app. Can somebody tell me how this is done? Below is my code which doesn't work when I try to create an AssemblyCatalog with the current executing assembly.
[Export(typeof(IPluginControl))]
public partial class MyPluginControl : UserControl, IPluginControl
[Import]
public string Message { get; set; }
public MyPluginControl()
{
InitializeComponent();
Initialize();
}
private void Initialize()
{
AggregateCatalog catalog = new AggregateCatalog();
catalog.Catalogs.Add(new AssemblyCatalog(Assembly.GetExecutingAssembly()));
CompositionContainer container = new CompositionContainer(catalog);
try
{
container.ComposeParts(this);
}
catch (CompositionException ex)
{
Console.WriteLine(ex.ToString());
}
}
}
You don't need to do this.
Just make sure that the catalog you're using when you import this plugin includes the main application's assembly.
When MEF constructs your type in order to export it (to fulfill the IPluginControl import elsewhere), it'll already compose this part for you - and at that point, will import the "Message" string (though, you most likely should assign a name to that "message", or a custom type of some sort - otherwise, it'll just import a string, and you can only use a single "string" export anywhere in your application).
When MEF composes parts, it finds all types matching the specified type (in this case IPluginControl), instantiates a single object, fills any [Import] requirements for that object (which is why you don't need to compose this in your constructor), then assigns it to any objects importing the type.