Git Product home page Git Product logo

vue-rx's People

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  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

vue-rx's Issues

How can I get observables of the base in the options of the derived ?

var Base = Vue.extend({
  subscriptions () {
    return {
      count$: Rx.Observable.create(function(observer){
          var cnt = 0;
          window.setInterval(function(){
              observer.next(cnt++)
          }, 1000);
      })
    }
  }
});

var Derived = Base.extend({
    subscriptions () {
        // How I Can get parent observables here ?

    }
});

I know I can get the count$ by this.constructor.super.options.subscriptions.call(me).count$, is there another way to get it?

Vue managed subscription error handling

When defining subscriptions in the subscriptions field or function there doesn't appear to be a way to attach an error handler to them. I like how convenient it is to just define an observable in these blocks and have Vue subscribe and expose the results to the component, but when subscriptions defined in this manner hit an error condition it breaks the application. Would it be possible to:

  1. Have a way to register an error handler for subscriptions that are created by Vue from this block
  2. If an error handler isn't defined, have vue route errors to the application level exception handler

Typescript definition not exporting properly

The docs mention importing like so

import Vue from 'vue'
import VueRx from 'vue-rx'

Vue.use(VueRx)

However this yields a TypeScript error: TS1192: Module '...node_modules/vue-rx/types/index' has no default export

I was able to work around this via

import Vue from 'vue'
import * as VueRx from 'vue-rx'

const vueRx: any = VueRx
Vue.use(vueRx.default)

And things seem to be working normally now.

Here's the relevant package versions I'm using:

  "rxjs": "^6.2.1",
  "vue": "^2.5.2",
  "vue-router": "^3.0.1",
  "vue-rx": "^6.0.0"

$watchAsObservable not being fired in unit tests

I am testing with karma, and I've notice this.$watchAsObservable('text') doesn't emit values even though this.text has changed.
Thanks.

The test:

it('should be saved after timeout', (done) => {
      const saveFileSpy = sinon.spy()
      const EditorWithMocks = EditorInjector({
        '../../../api/file-access': {
          saveFile: saveFileSpy
        }
      })

      const vm = createVm(EditorWithMocks)

      vm.text = 'pepo'
      vm.filePath = 'filepath'

      const inputTextArea = vm.$el.querySelector('.input-textarea')
      inputTextArea.textContent = 'p'
      dispatchInputEvent(inputTextArea)

      clock.tick(1000)
      Vue.nextTick()
        .then(() => {
          expect(saveFileSpy).to.have.been.calledWith('pepop', '123', 'filepath')
          done()
        })
        .catch(done)

The code:

saveFileSubscription: this.$watchAsObservable('text')
        .pluck('newValue')
        .debounceTime(settings.autoSaveTimeout)
        .distinctUntilChanged()
        .do(() => this.saveFile()),

subscriptions in the Vue options makes using @VueClassComponent clumsy

Since subscriptions is not declared in the Vue ComponentOptions interface adding it to the options when also using the @VueClassComponent decorator in Typescript causes the TS compiler to believe that the supplied parameter is an instance of VueClass (since it no longer fits the profile of a Vue ComponentOptions) - however the parameter really is an instance of ComponentOptions :-(

The only way I've found to avoid this is to use a set of casts on the argument to @VueClassComponent:

@VueClassComponent(<ComponentOptions<MyVueComponent>>{
  subscriptions: …
  props: …
})
export class MyVueComponent extends Vue {
…

If instead subscriptions was actually a method on the component (MyVueComponent) it would not be necessary to have a custom field added to ComponentOptions and the casts would not be necessary. I think the patch would be a few lines to look at vm.subscriptions if vm.$options.subscriptions were null/undefined. However I'm wondering if there's some reason why subscriptions must be part of the options that I'm missing?

$subscribeTo & subscriptions API when depending on a route param

Hi all :-)

I've got a problem regarding the subscriptions API. I have a piece of code like this:

import Vue from 'vue'
import numeral from 'numeral'
import { Observable } from 'rxjs/Observable'
import 'rxjs/add/observable/interval'
import 'rxjs/add/operator/switchMap'
import 'rxjs/add/operator/map'
import axiosObservable from '../lib/axiosObservable'

export default {
  name: 'Exchange',
  props: ['exchange_name'],

  methods: {
    exchangeFetch (exchangeName) {
      alert(exchangeName)
      return Observable
        .interval(3000)
        .switchMap(axiosObservable.get(Vue.config.infoCoinUrl + '/exchanges/' + exchangeName + '/market-pairs'))
        .map((response) => response.data)
    }
  },

  mounted () {
    this.$subscribeTo(
      this.exchangeFetch(this.exchange_name),
      (data) => {
        this.market_pairs = data
      })
  },
  data () {
    return {
      market_pairs: []
    }
  },

the idea here is that the dataset returned by the ajax call in exchangeFetch() depends on the exchange_name prop. I'm having the issue that the alert runs only when the page first loads and the AJAX call is fixed to the first value of exchange_name prop.

This is a bit surprising because I'd expect mounted() to be run on every render, so this kinda +should+ work, possibly, it follows the general docs online, yet it doesn't work.

I'm a bit new at JS, Vue, React, all of it :-) and I'm not sure if this is an issue with the framework or my inexperience (so I wrote an SO question too), yet this seems like a common use case, worthy of docs possibly :-)

PS I opened a vue-rx tag on SO love the project :-)

RxJS "pipeable" operators support

RxJS now supports "pipeable" operators, it might make sense to support passing in the operator references through the Rx object bag during initialization, and then fallback to looking on the prototype. That might also make it easier to support other Observable implementations by letting the library users pass in adapter functions for their particular flavor of Observable. Areas like here

Invalid observable found - what am I missing?!

Hi guys,

I've been trying to add a subscription/observable to my component using the guide in the Readme.

  subscriptions () {
    // declaratively map to another property with Rx operators
    return {
      aPlusOne: this.$watchAsObservable('prompt.choices')
        .subscribe(({ newValue, oldValue }) => console.log('choices', newValue, oldValue))
    }
  },

However I get this error in my dev tools console. No clue as to why it is invalid. What are the rules, what am I missing. Not entirely clear from the docs. Do I need to pre-define it somewhere?

vue.common.js?4eb4:2643 [Vue warn]: Invalid Observable found in subscriptions option with key "aPlusOne". 
(found in component <prompt-checkbox> at /Users/kristianmandrup/repos/vue-projs/app-generator/app/src/components/Prompt/Checkbox.vue)

I'm trying to react to updates on a set of checkboxes in order to save those values in my store so other components can reflect on it... However I can't seem to find a way to do it.
Maybe using simple watch? I tried without luck using on-change handlers, but they only pass true|false on, so I have no idea which checkbox the changed value is coming from :O

    <md-checkbox 
      v-for="choice in prompt.choices" 
      :name="prompt.name"
      :id="prompt.name"
      @input="updateChoice"
      @change="updateChoice($event)" 
      class="md-primary" 
      v-model="choice.value">{{ choice.label }}</md-checkbox>

I always receive simply true or false in my updateChoice(e) method :(
Is watch the way to go!? or computed properties? Doesn't seem right, coz then I would have to watch/react to the entire object iterated and bound to by the checkboxes.

Please advice :) Thanks!

vue-observable status

@yyx990803 @regou I'm liking directives more and more and so I'm keen on seeing the v-ob directive proposed in issue #14 become part of vue-rx/observable. Can it be merged in or is there some problem with it?

In reviewing various vue-rx issues there seem to be a few more suggestions raised. Maybe these be resolved into a next release? We are almost at 500 stars so that should mean that this room is getting brighter for sure.

After preparing other aspects of my project I'm back to taking a look at how the Vue reactivity engine and the Observable engine can work in a harmonious way, my specific requirements are always the catalyst. Have some new strategies I'm working through in my project, always interested in discussion.

Cannot read property 'installed' of undefined

Trying to add vue-rx to a TypeScript project:

Getting the following error:

vue.esm.js?ae66:4080 Uncaught TypeError: Cannot read property 'installed' of undefined
    at Function.Vue.use (eval at <anonymous> (build.js:766), <anonymous>:4081:15)
    at eval (eval at <anonymous> (build.js:982), <anonymous>:8:15)
    at Object.<anonymous> (build.js:982)
    at __webpack_require__ (build.js:658)
    at fn (build.js:86)
    at Object.<anonymous> (build.js:1422)
    at __webpack_require__ (build.js:658)
    at build.js:707
    at build.js:710

main.ts

import Vue from 'vue'
import App from './components/App.vue'
import store from './store'
import Rx from 'rxjs/Rx'
import VueRx from 'vue-rx'

Vue.use(VueRx, Rx)

new Vue({
  el: '#app',
  store,
  render: h => h(App)
})

The rest of the project: https://github.com/johnlindquist/vue-typescript-simple/tree/master/template

Any insights?

Typescript types are incompletes

Hello,

We are using vue-rx with typescript and we encountered some issues:

  • In subscriptions we can access to the properties defined in data but the current vue-rx types say that we can't.

Note: It works if you use: subscriptions?: Observables | (() => Observables) instead of subscriptions?: Observables | ((this: V) => Observables). But i didn't make a pull request because i am not sure that we can access to the props when subscriptions is called.

  • this is not extended with the data set by the subscriptions. So we can not access to the current values in the methods etc.

initialization timing still has problems.

Now the initialization runs in beforeCreate without messing up original dataFn. But this makes properties in subscriptions not able to use other properties in data, computed, props.

That's problematic since in most times we need to do things like this:

data: {
  a: 1
}
subscriptions: {
  b: someObservableMaker(this.a) // this maker takes this.a as param to make an observable.
}

I guess this would be the best way to achieve our goal (write in coffee):

beforeCreate: ->
  obs = this.$options.subscriptions
  if typeof obs is 'function' 
    obs = obs.call this
  return if !obs
  for ob of obs # for each key in obs 
    # use {} value to take the position in advance. **Cannot be undefined**
    # has to be {} in order to be used by others during creating
    defineReactive this, ob, {} 

created: ->
  obs = this.$options.subscriptions
  if typeof obs is 'function' 
    obs = obs.call this
  return if !obs
  for ob of obs # for each key in obs 
     ... # do the converting job for this[obs]

Can a non-child components be a observable

I have a usecase where a key input event within a component needs to be observed from a non child (sibling) component. Is this even possible without emitting event like vm.$emit

$fromDOMEvent can't listening root self scroll event

I tried to listen for the scroll event on vm root, but it didn't work because $fromDOMEvent delegated the scroll event to document.documentElement, but the scroll event didn't bubble up, please see the following demo:

<template lang="pug">
  section.drag-container-wrapper
    section.drag-container
</template>

<script>
  import { Observable } from 'rxjs'
  import { pluck } from 'rxjs/operators'

  export default {
    subscriptions () {
      const rootScroll$ = this.$fromDOMEvent(null, 'scroll')
        .map(e => console.log(e))

      return {
        rootScroll$
      }
    }
  }
</script>

<style lang="stylus" scoped>
.drag-container-wrapper
  height 600px
  border 1px solid green
  overflow-y scroll
  padding 10px

.drag-container
  height 1600px
  border 1px solid red
</style>

Any ideas?

environment

vue: v2.5.2
rxjs: v6.0
vue-rx: v6.0.0
chrome: v67

Why is immediate false by default?

When debugging why my component didn't work in a unit test, I found out that with $watchAsObservable, immediate is false by default. So that means that nothing got fired. I would have assumed that it would be true by default, as in most cases, that is what would be expected.

So is there any good reason to have it false by default? And can this be changed?

I'd like to help you rework this a bit

I think this library has some great goals, and I'd like to see it take full advantage of RxJS v6's modularity and "tree-shakability"

I recommend:

  1. Dropping support for RxJS 4
  2. Dropping the use of the Rx global
  3. Using RxJS 6 directly in this library (This will also enable supporting RxJS 5 if users want that)
  4. Getting users to use "pipeable" operators.

All of this will drastically simplify your codebase as well as make apps built with vue-rx and Webpack 4 a lot smaller.

Do i need unsubscribe

I have a question.I need unsubscribe in the angular.But i don't know in the vue.js how to do?Because Readme didn't say this.Maybe I don't need to worry this?

Is using the `subscribe` inside `subscriptions` is a good idea?

I want to use a stream with observableMethods into mounted () { with this.$subscribeTo but then I have an error:

Property or method "foo" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property. See...

When I use that into subscriptions everything is all right but I have to subscribe that observable so is it a good place for that? Is using the subscribe inside subscriptions guarantee unsubscribe before component will be destroyed?

Request: TodoMVC implementation

I think there should be an implementation of TodoMVC using vue-rx. Or if not the full TodoMVC, then at least a simple 'todo' example. A real world application's needs would probably align closer with the todo app than with the counter examples, and it would probably help new users better understand how to use it.

vue-rx using with jest TS2339

image

code

import { shallowMount, mount, Wrapper } from "@vue/test-utils";
import { CloudTable } from "@components/cloudtable/table";
import ElementUI from "element-ui";
import { systemTable } from "@store/table.store.attchment";
import Vue from "vue";
import VueRx from "vue-rx";

describe("src/components/cloudtable/table.ts", () => {
    let cmp!: Wrapper<CloudTable>;
    beforeEach(() => {
        Vue.use(ElementUI);
        Vue.use(VueRx);
        cmp = mount(CloudTable, {
            propsData: {
                moduleName: "usertable",
                config: systemTable["usertable"],
            }
        });
    });

    it("翻页事件是否正常", () => {
        cmp.find(".btn-prev").trigger("click");
        expect(cmp.vm.handleCurrentChange).toBeCalled();
    });

});

jest-config.json

{
    "rootDir": "../",
    "testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$",
    "transform": {
        "^.+\\.(t|j)s$": "ts-jest",
        "^.+\\.html$": "<rootDir>/test/html.tranform.js",
        "^.+\\.styl$": "<rootDir>/test/stylus.tranform.js",
        "^.+\\.css$": "<rootDir>/test/css.tranform.js"
    },
    "transformIgnorePatterns": [
        "<rootDir>/node_modules/(?!(element-ui|quill)/)"
    ],
    "globals": {
        "ts-jest": {
            "tsConfigFile": "tsconfig.json",
            "skipBabel": true,
            "enableTsDiagnostics": true
        }
    },
    "moduleFileExtensions": [
        "ts",
        "tsx",
        "js",
        "jsx",
        "json",
        "node"
    ],
    "moduleNameMapper": {
        "^vue$":"vue/dist/vue.common.js",
        "^vue-rx$":"vue-rx/dist/vue-rx.esm.js",
        "^@components/(.*)$": "<rootDir>/src/components/$1",
        "^@views/(.*)$": "<rootDir>/src/views/$1",
        "^@utils/(.*)$": "<rootDir>/src/utils/$1",
        "^@router/(.*)$": "<rootDir>/src/router/$1",
        "^@store/(.*)$": "<rootDir>/src/store/$1",
        "^@directives/(.*)$": "<rootDir>/src/directives/$1",
        "^@server/(.*)$": "<rootDir>/src/server/$1",
        "^@filters/(.*)$": "<rootDir>/src/filters/$1"
    }
}

tsconfig.json

{
  "compilerOptions": {
    /* Basic Options */
    "target": "es5",
    /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */
    "module": "commonjs",
    /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
    "lib": [
      "es2015",
      "dom",
      "es6",
      "es2016",
    ],
    /* Specify library files to be included in the compilation. */
    // "allowJs": true,                       /* Allow javascript files to be compiled. */
    // "checkJs": true,                       /* Report errors in .js files. */
    // "jsx": "preserve",                     /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
    // "declaration": true,                   /* Generates corresponding '.d.ts' file. */
    // "declarationMap": true,                /* Generates a sourcemap for each corresponding '.d.ts' file. */
    // "sourceMap": true,                     /* Generates corresponding '.map' file. */
    // "outFile": "./",                       /* Concatenate and emit output to single file. */
    // "outDir": "./",                        /* Redirect output structure to the directory. */
    // "rootDir": "./",                       /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
    // "composite": true,                     /* Enable project compilation */
    "removeComments": true,
    /* Do not emit comments to output. */
    // "noEmit": true,                        /* Do not emit outputs. */
    // "importHelpers": true,                 /* Import emit helpers from 'tslib'. */
    // "downlevelIteration": true,            /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
    // "isolatedModules": true,               /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */

    /* Strict Type-Checking Options */
    // "strict": true,
    /* Enable all strict type-checking options. */
    // "noImplicitAny": true,                 /* Raise error on expressions and declarations with an implied 'any' type. */
    // "strictNullChecks": true,              /* Enable strict null checks. */
    // "strictFunctionTypes": true,           /* Enable strict checking of function types. */
    // "strictPropertyInitialization": true,  /* Enable strict checking of property initialization in classes. */
    // "noImplicitThis": true,                /* Raise error on 'this' expressions with an implied 'any' type. */
    // "alwaysStrict": true,                  /* Parse in strict mode and emit "use strict" for each source file. */

    /* Additional Checks */
    // "noUnusedLocals": true,                /* Report errors on unused locals. */
    // "noUnusedParameters": true,            /* Report errors on unused parameters. */
    // "noImplicitReturns": true,             /* Report error when not all code paths in function return a value. */
    // "noFallthroughCasesInSwitch": true,    /* Report errors for fallthrough cases in switch statement. */

    /* Module Resolution Options */
    "moduleResolution": "node",
    /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
    //"baseUrl": "",
    /* Base directory to resolve non-absolute module names. */
    //"paths": {},
    /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
    // "rootDirs": [],                        /* List of root folders whose combined content represents the structure of the project at runtime. */
    // "typeRoots": [],                       /* List of folders to include type definitions from. */
    // "types": [],                           /* Type declaration files to be included in compilation. */
    // "allowSyntheticDefaultImports": true,  /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
    "esModuleInterop": true,
    /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
    // "preserveSymlinks": true,              /* Do not resolve the real path of symlinks. */

    /* Source Map Options */
    // "sourceRoot": "./",                    /* Specify the location where debugger should locate TypeScript files instead of source locations. */
    // "mapRoot": "./",                       /* Specify the location where debugger should locate map files instead of generated locations. */
    // "inlineSourceMap": true,               /* Emit a single file with source maps instead of having a separate file. */
    // "inlineSources": true,                 /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */

    /* Experimental Options */
    "experimentalDecorators": true,
    /* Enables experimental support for ES7 decorators. */
    "emitDecoratorMetadata": true
    /* Enables experimental support for emitting type metadata for decorators. */
  }
}

This should not be using the UMD/Global version of RxJS

As the RxJS project lead, I highly recommend just installing rxjs (v6 preferred) and importing and using it as normal. Otherwise, there will be severe application size and performance penalties when using this library.

If you need help, I'm happy to do so.

This is related to my findings while helping review #78

Observable with params.

Hi,
I am new to VUE ( I have an angular background ). Is there a way to and in the HTML something like this?

{{someObservable('value1')}}

{{someObservable('value2')}}

I need to watch on the same component multiple subjects depending on the value that is pass from the function.
Thanks in advance.

Can we use props as observables?

Hi, we are currently investigating switching to Vue.js from AngularJS and I don't see a way to use props as observables. This is what we have currently (with https://github.com/cvuorinen/angular1-async-filter):

<child my-attribute="$ctrl.myAttribute$ | async : this">
</child>

and then inside the child:

{{$ctrl.myAttribute}}

(The parent also got myAttribute$ injected with an attribute from ui-router)

The thing is that myAttribute$ can change, so it could be switched out with another observable. In AngularJS, the async filter (pipe) handles this for us, but from what I can see in the docs of vue-rx, there is no way to do this?

The only thing I think would work is using $watchAsObservable('myAttribute$').pipe(switchAll()) in the parent and then use that to inject into the child, but imho this use-case should be part of this solution, because it also needs to handle cases where the observable itself is undefined etc....

Any ideas?

Error in directive stream bind hook: "TypeError: Cannot read property 'apply' of undefined"

Hi!

I'm facing a problem installing VueRx.
By requiring entirely RxJs everything is fine:

var Vue = require("vue");
var VueRx = require("vue-rx");

var Rx = require('rxjs');

Vue.use(VueRx, Rx);

But when I try to reduce the bundle size:

var Vue = require("vue");
var VueRx = require("vue-rx");

var Rx = require('rxjs/Observable');
Rx.Subject = require('rxjs/Subject').Subject;
require('rxjs/add/operator/debounceTime');
require('rxjs/add/operator/map');
require('rxjs/add/operator/do');
require('rxjs/add/operator/mergeMap');

Vue.use(VueRx, Rx);

It's give me this error:
Error in directive stream bind hook: "TypeError: Cannot read property 'apply' of undefined"

Am I doing something wrong?

Thanks!

Emitted values are nested too deep in domStreams

Imagine a <parent> component that contains a <child> component.

The ChildComponent emits a "change" event, passing a value:

export default {
  name: "child",
  methods: {
    onChange(value) {
      this.$emit("change", value);
    },
  },
};

In the ParentComponent we use a stream to listen to those "change" events from the ChildComponent.

export default {
  name: "parent",
  domStreams: ["changeEvents"],
  subscriptions() {
    this.changeEvents
      .map(payload => payload.event.msg)
      .subscribe(value => {
        // do something with value
      });
  },
  components: {
    ChildComponent,
  },
};

Notice that the value emitted by the ChildComponent is nested two layers deep, meaning I have to .map(payload => payload.event.msg) to retrieve it. This feels unnecessarily complicated.

Is there some way to simplify this? What feels cleaner to me is one of the following in the parent component.

.map((payload, event) => event.msg)
.map((payload, value) => value)
.map((value, payload) => value)

Is there some way to cleanly achieve this for all vue-rx stream bindings? Am I approaching this the wrong way?

Proposal: subscribeAsEmit helper method

Admittedly a fairly trivial helper, but I know it would help with some boiler plate. And it gives a nice symmetry to the $fromEvent helpers

Basically:

function $subscribeAsEmit (name) {
  return (observable) => observable.subscribe(event => this.$emit(name, event))
}

New Feature v-stream directive

@yyx990803 The new v-stream directive is ready go, the PR #34 just needs to be merged. Having an updated version is important for ongoing development of my reactive product in Vue.

IMO, while v-stream is intended to replace $fromDOMEvent, both options could also co-exist in vue-rx.

Full on @stream integration

As someone new to Vue one of the first things I investigated was RxJS support, which landed me here, awesome! The example given in this repo is good and then I've seen another step up in how to integrate RxJS into Vue in the Summary section of the following link: http://www.christianalfoni.com/articles/2016_03_31_RxJs-the-smartest-dumbest-tool-ever

As I'm becoming acquainted with Vue I've seen the clean and elegant new @event syntax. As a result a thought entered my mind, which I would just like to share here. In essence reactive streaming API's like RxJS and others are here to stay, and support for Observables is coming to ES7: https://github.com/zenparsing/es-observable

That being the present and the future looking bright for both Vue and Observables I'm wondering if Vue might fully embrace Observables and support a @stream syntax?

dilemma between beforeCreate and created...

I realize that after the hook was changed from beforeCreate to created, now computed is initialized before subscriptions, so things in subscriptions cannot be used in computed. -_-~~

new Vue {
  subscriptions: {
    a: arrayFromSomeObservable;
  },
  computed: {
    b: function () {
      return this.a.length // not working.... coz this.a doesn't exist when this function runs for the first time
    }
  }
} 

A workaround is to change this.a.length to something like this.a === null? null : this.a.length (or this.a?.length in coffee). But don't seem neat....

Is there any way to overcome this while still being able to use this in subscriptions? puzzling...

Rx useful with vuex?

I have gone through the vue docs and Majesty of Vue.js etc. and are very much an admirer. Currently I am getting familiar with most.js, a reactive programming framework similar to RxJS, which seems very nice as well.

I am having a problem getting a clear picture whether it is still useful to use rx frameworks when using Vue plus Vuex. I read somewhere that the most.js streams are pretty much ‘decentralized vuex state variables’, which makes it sound like there is not much use for it then. On the other hand this repo suggests it’s useful, I suppose. So in what areas do they 'shine'? Tried some other places/ forums before posting here. Any comments highly appreciated!

processing data option in beforeCreate hook makes it impossible to use this in data option

This plugin runs the data function in the beforeCreate hook to transform observables to subscriptions, which makes it impossible to use this in data, since this does not exist when beforeCreate.

For example, sometimes we do this:

new Vue {
  data: function () {
    return {
      route: this.$route.path; // to get the current router path when this vue component is created.
      ...
    }
  }
}

But with this plugin we have to change it into this:

new Vue {
  data: function () {
    return {
      route: ''
      ...
    }
  },
  created: function () {
    this.route = this.$route.path; 
  }
}

It's okay for our own codes, but it gets painful when some third-party packages have this issue. In fact many plugins such as mint-ui have this issue, since using this in data is not very rare in practice.

So my suggestion is to move this data processing code to created hook instead of beforeCreate hook. I understand that, in created, if we add new properties to data we have to manually make them reactive, but in beforeCreate we don't need to do this. I guess this is why currently it's in beforeCreate. But considering the issue above, I think it's worth to make this change.

$fromDOMEvent doesn't work with events that don't bubble up

Hi!

It seems that the event delegation in $fromDOMEvent doesn't work with events that don't bubble up, like focus or blur.

It seems that, for events that don't bubble, you want to use event capturing when adding the event listener.

Took a quick look how CycleJS does it. They just look up the event in a list of events (https://github.com/cyclejs/cyclejs/blob/master/dom/src/MainDOMSource.ts#L28), and determine if the event should captured or not based on that (https://github.com/cyclejs/cyclejs/blob/master/dom/src/MainDOMSource.ts#L59).

TS definition files is not included

Hi. Thanks for adding TS files into this library.

I tried to use the new version, but types directory isn't included into npm packages.
Could you fix this?

Can't use createObservableMethod with RxJS 6

It looks like createObservableMethod will fail because of how it checks to see if share() is supported here.

if (!Rx.Observable.prototype.share) {...}

Right now, it is checking for support on the prototype of Observable when share() is actually somewhere around RxJS.operators.share(). Is there a way to address this through the new piping mechanism without having to utilize the rxjs-compat module?

This is sort of related to #69 but since createObservableMethod directly uses share() off the Observable prototype, the feature is broken.

obs in 'subscriptions' cannot be watched

subscriptions () {
  return {
    a: SomeObservable
  }
},
watch: {
  'a': function () {console.log('a changed!')}
}

When a changes, it cannot be watched. This might be due to obs in subscriptions are defined with Vue.util.defineReactive, which makes it reactive, but not watchable.

If adding test to data and use $subscribeTo in mounted to link test with SomeObservable, it works. But it seems not very neat writing in this way. I guess it would be best to put the obs into data.

FYI: `publish().refCount()` cannot be retried.

I was just looking through your code, and I noticed you're using publish().refCount() here

This becomes problematic if something downstream causes an error and you want to reconnect the observable. something like...

// Imagine the endpoint throws a 404 here.
o.$watchAsObservable('foo').switchMap(x => Observable.ajax.getJSON('http://endpoint/' + x)).retry(3)

It's a little edge-casey, honestly. And it can be easily worked around by moving the retry inside of the switchMap.

My first thought is you can solve this by replacing .publish().refCount() with .share(). They behave similarly, but share allows retries.

However, looking slightly more deeply, I think that what you're building on top of ($watch) is effectively multicast anyhow, so you probably don't need publish().refCount() in the first place, unless the underpinnings of $watch are particularly costly. It's really up to you.

Great work here, BTW!

Compatibility with mostjs (#observe vs #subscribe)

In readme, there is stated vue-rx can be used to subscribe to most.js observables, but it does not seem to work out-of-box. mostjs observables needs to be subscribed using observe method which does accept simple handler. vue-rx is calling subscribe method which expects Observer object (https://github.com/cujojs/most/blob/master/docs/api.md#subscribe)

functioning workaround:

{
    subscriptions () {
      const num = most.periodic(100).scan(x => x + 1, 0)
      num.subscribe = num.observe
      
      return {
        num,
      }
    },
}

I am new to observables, am I doing something wrong? Thanks.

vue-observable (rx) 2.0 observations

The addition of the new subscriptions option to a vm makes a huge difference, thanks Evan! There is now a place (sandbox) for observables to do their thing in. Using the subscriptions option it is possible to build any kind of observable while the method option remains for standard functions. Its a nice separation of concerns.

When I first encountered Vue and was learning the basics I saw an opportunity to bind RxJS directly into the Vue event system and I mentioned this in several issues here but never got any feedback on this idea. No one said a word but finally I came to the understanding that this binding could be achieved using a Vue Directive.

I suppose this directive could be added to this vue-observable plugin as well but I'm not even sure it is the most versatile idea anymore? Using RxJS alone (using fromEvent) it is possible to capture events from the DOM so why bother with the directive? Can someone tell me instead of me just always making what I consider positive suggestions!

Anyways, I just want to auto subscribe several observables when I create a component and capture their events as a streams. This looks like it is possible now so I can finally rest my battle weary head and enjoy the fruit of my quest for a good framework.

Based on feedback I'll kill this and the other issues I created and we can all move on in triumph :)

this.$watchAsObservable(...).pluck is not a function

When following the usage description and trying to watch a property as an Observable I get the following error in the browser console:

"this.$watchAsObservable(...).pluck is not a function"

My app environment looks like this:

"dependencies": {
"elasticsearch": "^12.1.3",
"material-design-lite": "^1.3.0",
"rxjs": "^5.0.3",
"vue": "^2.1.0",
"vue-locale": "^0.4.0",
"vue-material": "^0.6.3",
"vue-router": "^2.1.3",
"vue-rx": "^2.3.1"
},
"devDependencies": {
"autoprefixer": "^6.4.0",
"babel-core": "^6.0.0",
"babel-eslint": "^7.0.0",
"babel-loader": "^6.0.0",
"babel-plugin-transform-runtime": "^6.0.0",
"babel-preset-es2015": "^6.0.0",
"babel-preset-stage-2": "^6.0.0",
"babel-register": "^6.0.0",
"chalk": "^1.1.3",
"connect-history-api-fallback": "^1.1.0",
"css-loader": "^0.25.0",
"eslint": "^3.7.1",
"eslint-friendly-formatter": "^2.0.5",
"eslint-loader": "^1.5.0",
"eslint-plugin-html": "^1.3.0",
"eslint-config-standard": "^6.1.0",
"eslint-plugin-promise": "^3.4.0",
"eslint-plugin-standard": "^2.0.1",
"eventsource-polyfill": "^0.9.6",
"express": "^4.13.3",
"extract-text-webpack-plugin": "^1.0.1",
"file-loader": "^0.9.0",
"friendly-errors-webpack-plugin": "^1.1.2",
"function-bind": "^1.0.2",
"html-webpack-plugin": "^2.8.1",
"http-proxy-middleware": "^0.17.2",
"json-loader": "^0.5.4",
"cross-env": "^3.1.3",
"karma": "^1.3.0",
"karma-coverage": "^1.1.1",
"karma-mocha": "^1.2.0",
"karma-phantomjs-launcher": "^1.0.0",
"karma-sinon-chai": "^1.2.0",
"karma-sourcemap-loader": "^0.3.7",
"karma-spec-reporter": "0.0.26",
"karma-webpack": "^1.7.0",
"lolex": "^1.4.0",
"mocha": "^3.1.0",
"chai": "^3.5.0",
"sinon": "^1.17.3",
"sinon-chai": "^2.8.0",
"inject-loader": "^2.0.1",
"babel-plugin-istanbul": "^3.0.0",
"phantomjs-prebuilt": "^2.1.3",
"chromedriver": "^2.21.2",
"cross-spawn": "^4.0.2",
"nightwatch": "^0.9.8",
"selenium-server": "2.53.1",
"semver": "^5.3.0",
"opn": "^4.0.2",
"ora": "^0.3.0",
"shelljs": "^0.7.4",
"url-loader": "^0.5.7",
"vue-loader": "^10.0.0",
"vue-style-loader": "^1.0.0",
"vue-template-compiler": "^2.1.0",
"webpack": "^1.13.2",
"webpack-dev-middleware": "^1.8.3",
"webpack-hot-middleware": "^2.12.2",
"webpack-merge": "^0.14.1"
},
"engines": {
"node": ">= 4.0.0",
"npm": ">= 3.0.0"
}

throwing up error when i load bootstrap in vue

import Vue from 'vue'
import VueRouter from 'vue-router'
import vueResource from 'vue-resource'
import VueSession from 'vue-session'
import VueModal from 'vue-js-modal'
import VuePopper from 'vue-popperjs'
import VueJQuery from 'jquery'
import Bootstrap from 'bootstrap'

import app from './App.vue'
import {routes} from './route.js'

Vue.use({VueJQuery});
Vue.use(VuePopper)
Vue.use(VueSession, {persist: true})
Vue.use(VueRouter)
Vue.use(vueResource)
Vue.use(VueModal)
Vue.http.options.root = 'http://localhost:1337/';
Vue.use(Bootstrap);

Uncaught TypeError: Cannot read property 'install' of undefined
at Function.Vue.use (vue.esm.js?efeb:4680)
at eval (main.js?3479:20)
at Object. (build.js:1056)
at webpack_require (build.js:679)
at fn (build.js:89)
at Object. (build.js:905)
at webpack_require (build.js:679)
at build.js:725
at build.js:728

I keep getting this issue only when i add the use part of bootstrap

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.