Delete an event from state and server from a list of events with Vuex ORM - vuex-orm

I am able to remove events from their state with Vuex ORM with the following from a .vue file:
...
<tr v-for="event in events"
...
<i class="fa fa-trash-o" #click="destroyEvent(event)"></i>
</tr>
export default {
methods: {
destroyEvent(event) {
EventsModel.delete(event.id)
}
}
}
But this only removes it from its state, so when i reload the page, the events come back. How can I remove them from the server as well as the state with Vuex ORM?

Solved with EventsModel.delete(url_path, option)

Related

Passing multiple data points to an action? VUEX

So I have a form that collects 3 data points that looks like this:
<form class="" >
<table>
<tr>
<td>Maximum Temperature</td>
<td><input class="setSettings" v-model="settings.maxTMP" type="number" max="30" min="5"></td>
</tr>
<tr>
<td>Minimum Humidity</td>
<td><input class="setSettings" v-model="settings.minHUM" type="number" max="95" min="20"></td>
</tr>
<tr>
<td>Maximum CO2</td>
<td><input class="setSettings" v-model="settings.maxCO2" type="number" min="200" max="5000" step="10"></td>
</tr>
</table>
<button type="button" v-on:click="whatSettings(settings)">Update Settings</button>
</form>
My data in the script tag is stored in the components local data, not the store, ike this:
data: function() {
return {
settings: {
maxTMP: "",
minHUM: "",
maxCO2: ""
}
}
}
There's no reason to put it through a mutation and commit it to the store as the purpose for the action is merely to send the data via post request to receiving api.
My methods for the component look like this:
methods: {
...mapActions({
setSettings: 'setSettings'
}),
whatSettings(settings){
let foo = settings.maxTMP;
let bar = settings.minHUM;
let uhm = settings.maxCO2;
console.log(foo);
console.log(bar);
console.log(uhm);
this.setSettings(foo,bar,uhm)
}
},
And that action from the store is write like this:
setSettings(foo,bar,uhm) {
console.log("Set these settings");
console.log(foo);
console.log(bar);
console.log(uhm);
},
Please forgive all the console.log()'s. I have it like this cause I was trying to test out different combinations of things to figure out where it goes wrong. Right now when I click the Update Settings button the console prints the whatSettings() correctly so I know that foo, bar, uhm are the correct value as they are passed into the setSettings() action. The problem is in the action's logs. "Set these settings" and foo are printed correctly followed by a single undefined, not two. So I'm not sure exactly what's happening with bar & uhm. When I rearrange the order it's always the first that gets printed.
Is it a problem with multiple arguments being passed to the action? Ideally I would just like it to look like this directly in the button tag for neatness but that didn't work so I tried trouble shooting like this:
v-on:click="this.setSettings(settings.maxTMP, settings.minHUM, settings.maxCO2)"
Thanks for reading and I appreciate the help!
Well, after a little more looking around I found this and it fixed my problem: Axios post request with multiple parameters in vuex action
correct button tag:
<button type="button"
v-on:click="setSettings({
foo: settings.maxTMP,
bar: settings.minHUM,
uhm: settings.maxCO2
})"
>Update Settings</button>
correct vuex store action:
setSettings({commit}, {foo, bar, uhm}) {
console.log("Set these settings");
console.log(foo);
console.log(bar);
console.log(uhm);
},
Not entirely sure why the {commit} needs to be present, but it does otherwise I just get 3 undefined results in the log. But it works now!

Prevent closing browser tab when form is dirty in Angular 2

How to prevent closing browser tab when form is dirty in Angular 2?
My html body contains a component:
<body>
<my-app>Loading, please wait...</my-app>
</body>
which contains a router navigation and a router outlet:
<nav>
(...)
</nav>
<router-outlet></router-outlet>
and when the router navigates to the edit page, I have some form there:
<form #myForm="ngForm">
<button pButton type="text" label="Save" (click)="onSave()" [disabled]="!myForm.valid || myForm.pristine"></button>
</form>
Now, if the form is not 'pristine', I want to ask for confirmation when the user tries to close the browser tab:
window.onbeforeunload = function() {
if (form.dirty) {
return "You have unsaved data changes. Are you sure to close the page?"
}
}
How can I access the dirty state of Angular form in canonical way from there? I could register an event to field change on each field and set the global dirty flag, but I'd have to put that code on every from and by every navigation and then maintain that code so that the message stays consistent. Is there any other way to check out if there's an angular form on the page, which is in dirty state?
Perhaps
#HostListener('window:beforeunload', ['$event'])
handleBeforeUnload(event) {
if (connected) {
return "You have unsaved data changes. Are you sure to close the page?"
}
}
Add a Hostlistener decorator. If there are unsaved changes on the form confirm dialog appears.
#HostListener('window:beforeunload', ['$event'])
handleBeforeUnload(event: Event) {
event.returnValue = false;
}
This works. Implement the hasUnsavedData() function accordingly.
hasUnsavedData(){
return this.myForm.dirty;
}
#HostListener('window:beforeunload', ['$event'])
handleBeforeUnload($event: any) {
if (this.hasUnsavedData()) {
$event.returnValue = true;
}
}
Simply you can use Jquery to get state of ng-form.
#HostListener('window:beforeunload', ['$event'])
beforeUnloadHandler(event) {
if($('form').hasClass('ng-touched')) { //You can check with ng-dirty based on your requirements.
let confirmMessage = 'You have unsaved data changes. Are you sure to close the page?'
event.returnValue = confirmMessage;
return confirmMessage;
}
}
In my case am just showing warning dialog if that the form has been touched.
Try this directive https://github.com/extremeprog-com/ng-prevent-navigation.
So it should be simple
<div ng-prevent-navigation="vm.pageShouldBeReloaded"
ng-prevent-navigation-text="Payment form has unsaved changes.
If you leave the page now you will lose those changes."
></div>

Rxjs workflow for MongoDB Document References

I am developing an application on Ionic2/rc0. I got a ReplaySubject on a singlenton service that keeps the current user consistent across the whole app. It all works fine, I can subscribe to it and get a User object as easy as
this._user.Current.subscribe(user=>{ console.log(user)});
The User object looks like this
User {
confirmed:true
devices:["57f65werwe343bn8843f7h","7yr3243h5429hf2hjd"]
friends:["t245y53h65346htyh","356ytrer75dfhg43we56df"]
email:"francescoaferraro#gmail.com"
id:"57f6525e926bbc7615fc5c5c"
notification:false
password="$2a$04$.Fk/8eMj18ZrkfurbbdP4uT3yOs7Lb9db74GkNfgtABVY.ez2Q0I."
picture:"https://api.cescoferraro.xyz/kitty"
role:"master"
username:"cesco"
}
As you can see my backend is using MongoDB with One-to-Many Relationships with Document References as described here.
I have created a devices tab where I want to display all data about those user devices, but I need to call this._devices.info for each one of current.devices and concat the result back to TrueDevices
#Component({
template: `
<ion-header>
<ion-navbar>
<ion-title>Tabs</ion-title>
</ion-navbar>
</ion-header>
<ion-content>
<h2>Device:list</h2>
<h2 *ngFor="let item of devices | async">{{item}}</h2>
<button ion-button (click)="readDevice()">Read Random Device</button>
</ion-content>
`
})
export class DeviceComponent {
devices: Observable<string[]>;
TrueDevices: Observable<Device[]>;
constructor(public _user: UserService, public _device: DeviceService) {
this._user.Current.subscribe(user=>{ this.devices = Observable.of(user.devices)});
// Get current User
// call this._devices.info for each one of current.devices
// concat the result back to TrueDevices
this._user.Current
.subscribe((result) => { console.log(result) });
}
readDevice(){
console.log(this.devices);
this._device.info(this.devices.value[0]).subscribe(data=>console.log(data))
}
}
I will need to repeat the same procedure to the friends tab and so on. I am pretty sure there are a couple operators that would do the magic, but I am fairly new to rxjs and not familiar with all of them. Whats the right approach?
this._user.Current
.switchMap(user => Observable.from(user.devices)) // after this line, you have an Observable<string>
.mergeMap(device => this._device.info(device)) // each device will be mapped to another observable(or stream), and all the streams will be merged together
.toArray() // wait for all the streams to complete and reduce all the results into an array.
.subscribe(array => console.log(array));
or go to the gitter room:
https://gitter.im/Reactive-Extensions/RxJS

Passing selected value of a select to form action

I have a menu that I want to differ based on which account is currently selected in the system.
I have a page that allows a user to select an account from an html select. When the user submits the form from the account selection page I want to call the menu method on my controller passing in the selected value so my url looks correct.
Here is the existing template from the page that allows a user to select an account:
#helper.form(action = routes.Accounts.menu {
<table>
<tr>
<td><select id="accountNames">
#accountNames.map { name =>
<option value="#name">#name</option>
}
</select></td>
</tr>
<tr>
<td>
<p>
<input type="submit" value="Choose">
</p>
</td>
</tr>
</table>
}
From my routes file:
GET /account/:accountName/menu controllers.Accounts.menu(accountName: String)
How do I reference the selected value from my select (id="accountNames") and pass it into my form action?
Actually I think you're on the wrong side for doing that.
If the form's action has to change over the use of your 'select', it has to be done using JS.
So when the form is submitted (event submit) you have to update the url.
This can be done easily using javascriptRoutes.
So you have to do several things:
1/ create the javascriptRouter (assuming your add it in Application.scala)
def javascriptRoutes = Action {
Ok(
Routes.javascriptRouter("playRoutes")(
//accounts
controllers.routes.javascript.Accounts.menu
)
).as("text/javascript")
}
2/ define it in your routes file
# Javascript routing
GET /assets/javascripts/routes controllers.Application.javascriptRoutes
3/ add the related javascript file import in your views, let say in main.scala.html
<script type="text/javascript" src="#routes.Application.javascriptRoutes"></script>
4/ add a submit handler to your form that does that before executing the default behavior
$("form").submit(function () {
//this computes the correct URL giving a parameter which is the value of the selected option
var newURl = playRoutes.controllers.Accounts.menu($("#accountNames").val()).url
$(this).attr("action", newUrl);
})
Notice how we've used playRoutes both in the controller (1) and the JS call (4).

knockout - notify when 'with' directive is fired

Hi I have the following scenario.
Some elements are nested within a with
<!-- ko with: model.selected_item -->
<tr>
<td style="width:20%">Name:</td>
<td style="width:80%" class="field" data-bind="text: name"></td>
<td style="width:10px"><div class="btn_edit"></div></td>
</tr>
<tr>
etc...
<!-- /ko -->
$("div.btn_edit", component.context).on("vclick", function(e){
//edit it
}
The problem I have is that if the selected_item changes - I loose the bindings on the edit button.
In this scenario, it is a little difficult to subscribe to the model.selected_item and reapply the bindings - so I'd like to get notified when the elements within the with directive are updated and reapply then.
Is there a knockout specific way to achieve this?
An help much appreciated.
The reason you are getting this problem is that the click handler element is being destroyed by the template engine each time you update item.
Here is an example of the way to achieve what you want without resorting to jquery delegate bindings, which while they do work they are poluting your otherwise nice KO model with needless dom operations. Everytime I find myself using the old $() selector with a KO app I have to seriously consider whether there is a better model oriented way.
http://jsfiddle.net/madcapnmckay/EFQ9S/
The gist of this is to convert your model into true js classes and use those to bind KO click events rather than jquery click handlers. The beauty of this approach is that KO will rebind for you elements when they get destroyed.
var item = function (config) {
var self = this;
this.name = ko.observable(config.name);
this.edit = function () {
$("body").append("<div>lets edit " + self.name()+"</div>");
};
};
var model = function() {
this.item = ko.observable();
this.pushNew = function () {
this.item(new item({name: "new name"}));
};
}
$(document).ready(function(e) {
var mymodel = new model();
ko.applyBindings(mymodel);
mymodel.item(new item({ name: "the_name" }));
})
Hope this helps.