GithubHelp home page GithubHelp logo

figuredlimited / vue-mc Goto Github PK

View Code? Open in Web Editor NEW
627.0 24.0 97.0 1.84 MB

Models and Collections for Vue

Home Page: https://vuemc.io

License: MIT License

JavaScript 59.28% TypeScript 40.72%
vue vuejs data-structures models collections validation

vue-mc's Introduction

Models and Collections for Vue.js

Build Status Coverage Latest Version License

Documentation

Documentation is available at http://vuemc.io

Development

Install

Install yarn if you don't already have it available:

sudo npm install -g yarn

Install the dependencies:

yarn

Build

yarn build --watch

Test

yarn test --watch

Docs

You will need to install jekyll to render and edit the documentation.

yarn docs

License

MIT

vue-mc's People

Contributors

aanais avatar amirimatin avatar behindthemath avatar brunobg avatar cichy380 avatar daleevans avatar dependabot[bot] avatar djsmedes avatar dylan-chapman avatar fakocher avatar flygenring avatar jhsc avatar kvdveer avatar lino avatar loonytoons avatar martinarisperiveros avatar mihailrussu avatar mnagy avatar rdarcy1 avatar rtheunissen avatar sergiuwd avatar sifex avatar tgaff avatar throrin19 avatar tosty33 avatar yugo412 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

vue-mc's Issues

Lodash iterators break when adding a "length" attribute

I was seeing strange issues where many methods on the Model class were not working correctly. As minimal example:

class Test extends Model {
  defaults() {
    return { length: 0 };
  }
  validation() {
    return { length: positive };
  }
}

test = new Test();
// test.attributes is an empty object
// test.validate() is true

Looking into it more, I found that lodash iterators use the presence of the length attribute to determine if an object is an array or not. This causes all objects passed into lodash to be treated as an array.

I image I could override the rest calls to rename these properties coming from the server, but I'm wondering if there is an officially sanctioned way of dealing with reserved names, or if this is a problem that has not been considered.

Required fields not working when saving collections

On my model my fields are"

// I have all these types imported
// All the other validation rules seem to work asides from required
validation() {
    return {
        attribute1: integer.and(gte(1)).and(required),
        attribute2: dateformat('YYYY-MM-DD').and(required),
        attribute3: number.and(required),
        attribute4: number.and(required),
    }
}

I have a collection that holds these models, when I save the collection model objects that don't have all the required fields pass validation and get sent in my payload to the back end.

Example:
This object below will pass validation even through attribute4 is marks as required in the model:

let obj = new MyModel({
    attribute1: 32123,
    attribute2: '2018-07-09',
    attribute3: 23452345,
})

I have tried explicitly defining options to force validation (even through the default for validateOnSave is true and I still can figure out how to force my validation rules.
This seems to only happen will the required constraint, when saving collections bad formats are always caught.

Is there any ways to add attributes in Collections?

Hello,

This lib. is much useful particularly for me to built frontend in Vue & backend powered by Laravel. I was having to question/suggestions if it is not already included.

  1. Is there any way to add a custom attribute to collections? What I want to do is append some parameters to fetch url.
  2. Is there any way to add custom HTTP methods to model other than CRUD?

Collection fetch with queries

Im not understand in documentation, how can I fetch data by collection class with queries?

var offers = new OffersCollection();
offers.page(1).fetch(() => {}); //Request with page sent, models in collection exist.

But how I can add dynamic parameters, for example: "...&param1=123&param2=321"?

Document getModelsFromResponse

Hi there! Playing around with VueMC to see if it's a good fit for the project I'm working on. I'm working with a server who's responses are of the following format:

// GET /api/widgets
{
    "page": 0,
    "per_page": 10,
    "items": [
        {
            "_id": "5a01fea69d8a3a4ce8a70bbd",
            "label": "FOO"
        },
        {
            "_id": "5a01feab9d8a3a4ce8a70bbe",
            "label": "BAR"
        }
    ]
}

Using Collection.fetch(), I've been seeing the following error thrown:

"Expected an array of models in fetch response"

I went ahead and overwrote the getModelsFromResponse method in my Collection class definition, but I had to do a bit of digging to get there:

  getModelsFromResponse (response) {
    let models = response.getData().items
    ...
  }

Is this the preferred approach with VueMC? With Backbone.js one typically defines a parse method on Models or Collections to handle variations in response form - I want to ensure that the overwriting the getModelsFromResponse method is the VueJS analogue to this approach. If so, I think it would be a valuable addition to the documentation and I would be happy to help with that endeavor :)

Also - as a side note - if this.isPaginated() does return true, it would be nice if the user could specify an alternative to the data field without overwriting the entire method:

    // We're making an assumption here that paginated models are returned
    // within the "data" field of the response.
    if (this.isPaginated()) {
      return _.get(models, 'data', models)
    }

Multiple layers of filtering results in infinite update loop

My setup is roughly:

import { Trips } from "models";

export default {
    data: () => ( {
        date: "2018-06-15",
        trips: new Trips()
    } ),

    async created() {
        await this.trips.fetch();
    },

    computed: {
        selectedDateTrips() {
            return this.trips.filter( trip => trip.deliveryDate === this.date);
        },

        numCompletedTrips() {
            return this.selectedDateTrips.filter( trip => trip.status === "Completed" ).length;
        },

        numScheduledTrips() {
            return this.selectedDateTrips.filter( trip => trip.status !== "Completed" ).length;
        }
    },

    render() {
        return <p>{this.numCompletedTrips} completed trips, {this.numScheduledTrips} scheduled trips</p>;
    }
};

This gives the Vue error:
"[Vue warn]: You may have an infinite update loop in a component render function."

This seems to happen whenever I'm doing two layers of filtering on an initial collection (this.trips -> this.selectedDateTrips -> completed/scheduled trip count).

This example may seem a little contrived (why don't I pass date to my api call?), but my actual setup is a bit more complicated, but essentially boils down to this.

Is there a way to avoid this?

use sort() in template

Hi,

I've got this list of items that I want to be displayed in a certain sort order. I thought I'd use it in a template like:
<item v-for="item in itemList.models.sort('field')"></item>
but since sort() doesn't return anything this doesn't work

I've 'solved' this by sorting anytime an item is added or when an item has changed. This way it's not possible to display the list twice in different sort orders.

Any suggestions?

new RegExp with flags might cause issues on IE when passing a previous regular expression

While creating a new RegExp object with defined flags from previous regular expression, the following code won't work on IE:

new RegExp(/(ab|bc)/, 'g');

Possible solution is to seek for source property on previous object and pass it as the first argument:

var a = /(ab|bc)/;
new RegExp(a instanceof RegExp ? a.source : a, 'g');

This issue appears on Structures/Base.js => getRouteReplacements method.

The following method replacement might do the work:

    getRouteReplacements(route, parameters = {}) {
        const replace = {};
        let pattern = this.getRouteParameterPattern();
        pattern = new RegExp(pattern instanceof RegExp ? pattern.source : pattern, 'g');

        for (let parameter; (parameter = pattern.exec(route)) !== null; ) {
            replace[parameter[0]] = parameters[parameter[1]];
        }

        return replace;
    }

Better support for nested models and collections

At the moment the support for nested structures is limited. We'd like to improve this as it's a common situation and should in theory work as you would expect. This issue is a place to collect all the things we'd like to achieve when we get to improving this support.

  • Errors should be set on the child, not with dot notation on the parent. (or both?)
  • Determine the difference between parent.saved('child.attr') and parent.child.saved('attr')
  • Provide a nice mechanism to convert nested objects to models

Possibility to extend request on fetch params

It's possible to extend axios params on fetch() method ? Like that :

const config = {
    // axios specific config
};


collection.fetch(config);

The use case is really simple. In many parts on development app, we can use same collection or model Classes but fetch differents parameters (like with a filter query, specific orders, ...). And it's mote simple to use fetch params instead of extend collection/model methods.

ResponseError

"Expected an array of models in fetch response"

this is my json response:
code: 200
data:[{id: 1, cif: "B12312312", razon_social: "Formacion Futuro S.L", email: "[email protected]",…}]
message: null
status:true


I can´t get my response. What is the proble?

Changelog

It would be quite helpful with an overview of changes between versions that is more detailed than the release and less than the commit overview.

Whether it's kept in the readme, the documentation, the release overview, or somewhere else is a matter of taste, but I think it should be kept and might as weel be kept public ;)

Use without laravel

I'm able to use this with any rest service that uses laravel pattern for endpoints? I have a restful springboot application and i would like to use together that, If I apply laravel pattern for the endpoints is it supposed to work fine or is there any limitation?

[Issue] Mutating to Collection causes Errors

Related to #9 (comment).

Issue

I've run into some errors where my User model has a MembershipList collection similar to below

{
	"name": "Test",
	"email": "[email protected]",
	"memberships": [
		{
			"id": 1
		}
	]
}

When I try to cast "memberships" to MembershipList, it seems to throw a tonne of Errors. Haven't looked too much into it, but from the outside it looked like a recursion error.

// Attribute mutations.
mutations () {
	return {
		memberships: (memberships) => {
			return new MembershipList(memberships)
		}
	}
}

so using the following seemed to solve it.

// Attribute mutations.
mutations () {
	return {
		memberships: (memberships) => {
			if (typeof memberships.models === 'undefined') {
				return new MembershipList(memberships)
			}
			return memberships
		}
	}
}

Possible (better) Solution

Seems like an easy fix to this is to just test to see if the collection is accepting an array or if it's accepting another one of itself.

Just a quick request to see if @rtheunissen is happy with me fixing this like that & I'll submit a PR.

Allow for async validation rules

As far as I can tell, it's currently impossible to have async validation rules.

Common scenario: You need to check if an email address is available or already taken when a user is changing their email address.

I'm migrating some validation from VeeValidate to models, and how they handle it is letting rules return a promise that resolves { valid: Boolean }. Docs Reference and Code Reference

Documentation suggests installing hidden globals

From documentation:

// Set the on the global on the window so that you don't have to import
// the base classes in every model and collection class or component.
window.Model = Model;
window.Collection = Collection;

This is really bad practice. It leads to maintainable code, and all kinds of conflicts. No-one should ever do that, and documentation should certainly not recommend it.

Importing these symbols is a single line, which has two purposes:

  1. explain to babel where to find the symbol,
  2. explain to the reader of the code what library is being used here.

Purpose no1 can be circumvented by using a global import, but purpose no2 is still really relevant, and should not be left out.

Document list of supported locales

Because not all locales are supported yet, I suggest documenting a list of supported locales so that one does not have to look into the source code for locale.js to see what locales are currently supported.

Custom response payload format

I'm trying to use vue-mc (which is awesome, by the way) and have run into an issue:

The API I'm working with is responding with a data and an optional meta field for every request. As far as I read from the docs, vue-mc is expecting the actual data to be in the root node of the response data instead of in a separate data field, as in this example. The meta field includes additional cursor data, that I can handle myself.

{
    "data": [
        {
            "id": "9788dd4e-d38b-4982-b1b5-41b1eb4d5a04",
            "foo": "bar",
            "bar": "baz"
        },
        {
            "id": "e1d26b1f-8085-4e4f-af49-44ca039c65b1",
            "foo": "bar",
            "bar": "baz"
        }
    ],
    "meta": {
        "current": "b5c30e88-f43e-421b-95ef-f45b891bf1c1",
        "next": "7d46c5f1-709d-4945-995e-a141c085ae21"
    }
}

How would I manage to make vue-mc get the data from the data field? In another issue I saw that I can override the Collections getModelsFromResponse() method. This works only for collections though.

Much easier would be to override Response.getData() globally, but I have no idea how this could be done.

ReferenceError: _ is not defined

I am using vue cli with webpack-simple. I am getting this error.I have install all dependencies of vue-mc. You can see my devDepencies:

  "devDependencies": {
    "axios": "^0.17.0",
    "babel-core": "^6.26.0",
    "babel-loader": "^7.1.2",
    "babel-preset-env": "^1.6.0",
    "cross-env": "^5.0.5",
    "css-loader": "^0.28.7",
    "file-loader": "^1.1.4",
    "lodash": "^4.17.4",
    "moment": "^2.19.1",
    "node-sass": "^4.5.3",
    "sass-loader": "^6.0.6",
    "underscore": "^1.8.3",
    "vue-loader": "^13.0.5",
    "vue-mc": "^0.1.1",
    "vue-template-compiler": "^2.4.4",
    "webpack": "^3.6.0",
    "webpack-dev-server": "^2.9.1"
  }

But I am getting this error.

vue-mc.es.js?c9ea:2456 
Uncaught ReferenceError: _ is not defined
    at eval (vue-mc.es.js?c9ea:2456)
    at Object.<anonymous> (build.js:1010)
    at __webpack_require__ (build.js:679)
    at fn (build.js:89)
    at eval (31:4)
    at Object.<anonymous> (build.js:934)
    at __webpack_require__ (build.js:679)
    at fn (build.js:89)
    at Object.<anonymous> (build.js:789)
    at __webpack_require__ (build.js:679)

image

Collection clearState sets loading to true

Is there a reason why Collection.clearState() sets loading to true, while Model.clearState() sets loading to false? Don't know if it's a bug or just some logic I'm not understanding.

Use axios instance instead of default axios

I recommand to use default axios instance instead of axios global requester.

If we set others headers, they are add to all axios requests. Not only collection or model requests

defineProperty with configurable

Im trying overwrite getters&setters for simple relations support, but get error can't redefine non-configurable property. Can you add please configurable: true, in registerAttribute for Object.defineProperty?

Strange behavior of property type Array

When define my model like this

  defaults () {
    return {
      'keys': []
    }
  }

  mutations () {
    return {
      'keys': Array
    }
  }

and response contains

{keys: [1,2,3]}

model contains next data

_attributes.keys === [[1,2,3]]

Delete model with fatal

Hi, I have a problem with vue-mc :

I try to remove an item on unexist route (I test my interface first). But, if the model.delete() failed, the deleting is already set to true and I can't retry without refresh my entire collection.

In a normal way, after the request, if it was an error, we can retry the delete. It's possible to fix that ?

Thanks

Map keys

I want to make a response keys mapping before requests are made and before response is assigned to model. Is this possible without overriding methods like onFetchSuccess()?

One thing that could work would having different mutators for responses and requests.

Axios configurations (client)

I need to set defaults for axios like "withCredentials" property, baseUrl, headers, etc (and also interceptos). I tried to set it to axios.defaults on app.js but it didn't work. How can I achieve this?

Error: Collection is not valid

Hello, thanks for you project!

Im get one error, but not understand why.

Model:

defaults(){
        return {
            places:new PlacesCollection(),
        }
}

Component:
MyModel.places.add();

Collection is not valid

Why its happen?

Use date-fns for date validations

Moment.js is a fairly large dependency, especially if this is the only package you have that's using it. It'd be nice if date-fns was used instead, or simply supplying a way to use non-date related validation rules without Moment being imported, then we can redefine our own date-related rules using whatever date library.

Sorting on the server

It would be nice to add functionality to implement sorting on the server, something like that:

model.page(1).sorting({ name: 'desc' }).fetch() => ?page=1&sort=name&order=desc

or set all query params

model.queryParams({ page: 1, sort: 'name', order: 'desc' }).fetch() => ?page=1&sort=name&order=desc

it would be convenient to use with route

{ params: this.$route.query }

More basic documentation and examples for fetching from an API

Would it be possible to get some more basic examples in the documentation. There isn't any examples of fetching from an api, only creating from a hard coded array.

Perhaps it's too simple a question but i've been really struggling. Right now this is the only thing I can get working to get an instance of a model from an API, but i'm sure it can't possibly be right as it seems far too convoluted.

// Task.vue
// The template would be displaying details about a single Task
export default {
        props: {
            taskId: {
                type: Number,
                default: 1
            },
        },
        created () {
            new Task({id: this.taskId}).fetch().then(response => {
                this.task = new Task(response.response.data);
            }).catch((error) => {
                console.log(error);
            });
        },
        data: function() {
            return {
                task: null
            };
        },
    };

// Json Response:
{"id":1,"title":"Task 1","description":"A description"},

All i'm trying to do is get a single instance of a Task, in Laravel it would look something like this:

$task = Task::find(1);

$task->doSomething();
echo $task->title;
// etc

How would you get a single instance of a Task with the id of 1 using vue-mc?

The documentation shows:

// Create a new task with initial attributes.
let task = new Task({title: 'Task 1'});

console.log(task.doSomething());
console.log(task.title);

But obviously that's not using fetch or getting data from a database?

Sorry for what is probably a very stupid and simple question but it's really not at all clear and hours of googling has got me nowhere. I've read every single issue hoping someone would at least have posted an example when having another issue, but there's nothing. It would be great if the docs had more examples of things like this even if it seems obvious to some people.

toArray and toObject

I'm surprised to see this library has no methods toArray and toObject on Collections and models to use this on non-compatibles vueJS components.

It's possible to add this vital functions ?

Thanks

Representing model relationships

Are you planning to add support for attributes that are models?
I'm not sure if the use case is general enough, but I was looking for the following:

  • A model is returned when calling get for that attribute on the model
  • The attribute is only marked as changed when a different models is set for the attribute (the related model's attributes can change without marking this attribute as changed)
  • The id of that model is passed for that attribute when saving

This might be along the lines of the feature you mention in Issue #39.

item.save() sets my item to default values

I'm using a backend that returns {result: 'ok'} when an update was succesful.
However :
item.onSaveSuccess() calls
this.update({result:'ok'} which in turn calls
this.assign({result:ok}) which calls
this.set(defaultsDeep({}, {result:ok}, cloneDeep(this.defaults())));

and presto: item is set to all defaults

I wonder how calling this.update() doesn't preserve the original content?

the comment in Model.update is:
// A plain object implies that we want to update the model data.
// It's not a requirement to respond with a complete dataset,
// eg. a response to a patch request might return partial data.

which is entirely true, but that's not what's happening.

nested collection problem

I have a model that have a collection as one of properties and i cant add new models
in that collection. It throw the error 'Error: Collection is not valid'. I find out that error is
happen because field _uid that defined in Base class is disappear on nested collection
because lodash deepClone doesn get it.

Or maybe there is another way to create a model with array of another model in the property?

Demo App

Hello,

There is a demo app? Would be very interesting!

Congratulations for the project.

Library not compatible with babel 7.0.0beta.48+

Hello, I have a problem with vue-mc and Babel.

If I update babel in last versions (7.0.0 beta 48 and more) I have this error on my project if I ass custom method on your Collection class :

Input Code

class MyClass extends Collection {
    setPageSize(pageSize) {
        this._pageSize = pageSize;
    }
}

const obj = new MyClass();

obj.setPageSize(12); // TypeError: obj.setPageSize is not a function

Babel Configuration (.babelrc, package.json, cli command)

{
    "plugins": [
        "lodash"
    ],
    "presets": [
        "poi",
        ["@babel/env", {
            "targets": {
              "browsers": [
                ">0.25%",
                "not ie 10",
                "not op_mini all"
              ]
            }
        }]
    ]
}

Environment

  • vue-mc version : 0.2.4
  • Babel version(s): 7.0.0-beta.48, 7.0.0-beta.49
  • Node/npm version: Node v8.11.1 / NPM v5.8.0
  • OS: OSX 10.13.4
  • Monorepo: yes
  • How you are using Babel: loader

I've create same issue on Babel repo : babel/babel#8063

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.