store.push not reflecting on template with ember-cli-pagination - javascript

I'm new to Ember.js and I'm trying to add an object to the store after an ajax request.
The problem is that it does not reflect on template if I use ember-cli-pagination.
If I use this.store.findAll in model, it works, but when I use this.findPaged it does not.
I'm using ember-inspector and the object appears in the store, just don't in the browser.
My code:
import Ember from 'ember';
import RouteMixin from 'ember-cli-pagination/remote/route-mixin';
export default Ember.Route.extend(RouteMixin, {
actions: {
create: function(email) {
let adapter = Ember.getOwner(this).lookup('adapter:application');
let url = adapter.buildURL('billing/delivery-files');
let store = this.get('store');
let modelName = 'billing/delivery-file';
return adapter.ajax(url, 'POST', {
email: email
}).then(function(data) {
var normalized = store.normalize(modelName, data.object);
store.push(normalized);
});
}
},
model(params) {
return this.findPaged('billing/delivery-file',params); //does not work
// return this.store.findAll('billing/delivery-file'); //works
}
});
Tried the solutions from this issue, and did not work at all.
What am I missing?

Figured out!
After pushing to the store, I needed to push to the paginated array a reference to the store object. Don't know exactly why but it worked like a charm!
model.content.pushObject(pushedRecord._internalModel);
In my case I wanted it at the first position of the array, so I did:
model.content.insertAt(0, pushedRecord._internalModel);

Related

Trying to get a value from a custom store Svelte

i want to ask something, i have a custom store like
const BlaBla = (Data) => {
const { subscribe, set, update } = writable(Data);
return {
subscribe,
update,
set,
setData: (NewData) => {
set(NewData)
},
getData: () => {
return <<<<<<< "Here lies the problem, how i can get the "newData"?."
}
}
}
i will explaying the scenario, im creating a script for a fivem server and im using svelte, i create a store that get a Vehicle with some properties like Name, Last Name, Plate and bla bla, i create the setData(Vehicle) and pass a set(Vehicle) then in another method i want to "get" the plate only, one solution i did was creating a variable in the scope and instead of a set i did an update like this
const VehicleStore = (Vehicle) => {
let Data = {} //Variable inside the scope
const { subscribe, set, update } = writable(Vehicle);
return {
subscribe,
update,
set,
setData: (NewData) => {
update((s) => {
s = NewData
Data = s
return s
})
},
getData: () => {
return Data.Plate
}
}
}
i don't know if this is the actual solution, i think im missing something
Svelte exports a get function that can be used to resolve the value of a store once (it is syntactic sugar around subscribe).
So first you have to get the value of the store, then you can access its property:
import { get } from 'svelte/store';
// ...
const store = writable(Data);
const { subscribe, set, update } = store;
// ...
return get(store).Plate
Note that accessing data like this will not be reactive because there is no persistent subscription to the store. You are generally not meant to use stores like that.
Instead you usually would use the store in a component's markup using auto subscriptions via $:
$VehicleStore.Plate

Vue.js - Data Property isn't accessible

I have a Vue.js 3 app. In this app, I'm trying to search through an array of object. I've created a fiddle here. In this fiddle, the code causing the issue looks like this:
async runSearch() {
let searchResults = this.data;
if (this.searchQuery) {
let info = JSON.stringify(searchIndex);
alert(info);
console.log(searchIndex);
searchResults = await courseIndex.search(courses);
}
this.results = searchResults;
}
For some reason, it's like searchIndex doesn't exist. However, I do have it in the model as shown here:
data() {
return {
searchIndex: null,
searchQuery: null,
data: data,
results: null,
}
}
What am I doing wrong? Why can't I execute a search?
use this.searchIndex to access reactive variables defined in data in Vue.

load json file before app startup and save it in global variable mithrilJs

I want to load a JSON file into my mithrilJs app before its startup and want to save this data in some global variable (JSON file is for some run time configuration of mithril application just like app_initializer in Angular)
so far I have done this in my app
import m from 'mithril';
import { a } from './MainView';
var Data = {
fetch: function() {
m.request({
method: "GET",
url: "./client/config/config.json",
})
.then(function(items) {
console.log(items)
// want to store this
m.route(document.body, "/accounts", a)
})
}
}
Data.fetch()
and my Main view file contains
import m from 'mithril';
import {Layout} from "./components/layout";
import {Accounts} from "./components/accounts";
import {AccountNew} from './components/newAccount';
export const a={
"/accounts": {
render: function (vnode) {
return m(Layout, m(Accounts))
}
},
"/accountsNew": {
render: function (vnode) {
return m(Layout, m(AccountNew))
}
},
}
so what could be better approach for this and also I want to store fetched json file data (items) in some global variable like props in react or services in angular , How I can do that to access everywhere in my app
The docs state that you can use onmatch to preload data, here is a rough translation of their example:
var state = {
items: null,
loadItems: function() {
if (state.items === null) {
return m.request("./client/config/config.json").then(function(items) {
state.items = items;
});
}
}
};
const a = {
"/accounts": {
onmatch: state.loadItems,
render: function (vnode) {
return m(Layout, m(Accounts))
}
},
"/accountsNew": {
onmatch: state.loadItems,
render: function (vnode) {
return m(Layout, m(AccountNew))
}
},
}
You can read their two examples in the documentation here: Preloading data.
Alternative solutions
These solutions don't really involve mithril because your are really loading the data before mithril is even used. You should be able to pass your state variable into the component as an attribute, ie. return m(Layout, m(Accounts, {state}));
Dumping JSON String into server side template
If you control the server side as well you can just dump your configuration directly into a global variable by outputting an escaped JSON string assigned to a javascript variable in your base template. I do this to dump model information or session information so my client side code can use it.
<script> var config = ${escapedJSONStringInServerVariable};</script>
Import config directly
You can also just import the configuration directly into your app if you rewrite your config.json to just export your configuration as an object.
import {Config} from ./client/config/config.js
Call m.request directly
Finally you can also just assign the promise returned from m.request to a var and return that promise in loadItems. This should fire m.request immediately but prevent the loading of your templates until the promise is resolved.
var state = (function () {
var configRequest = m.request({
url: "./client/config/config.json"
}).then(function(items) {
state.items = items;
});
return {
items: null,
loadItems: function() {
return configRequest;
}
};
})();
Try to save it in sessionStorage and check it after every reload.
if(!sessionStorage.key('myJson'))
sessionStorage.setItem('myJson','myJson')

Updating nested objects firebase

From the Firebase note:
Given a single key path like alanisawesome, updateChildren() only updates data at the first child level, and any data passed in beyond the first child level is a treated as a setValue() operation. Multi-path behavior allows longer paths (like alanisawesome/nickname) to be used without overwriting data. This is why the first example differs from the second example.
I am trying to use a single function createOrUpdateData(object) in my code. In case of update, it updates first level children properly, but if I have nested object passed, then it deletes all other properties of that nested object.
Here's the code:
function saveUserDetails(email,object){
var hashedEmail = Utilities.getHashCode(email);
var userRef = ref.child(hashedEmail);
return $q(function(resolve,reject){
return userRef.update(object, function(error){
if(error){
reject(error);
}else{
resolve("Updated successfully!");
}
});
});
}
So if I pass:
{
name: 'Rohan Dalvi',
externalLinks: {
website: 'mywebsite'
}
}
Then it will delete other properties inside externalLinks object. Is there a cleaner and simpler way of avoiding this?
In short, how do I make sure nested objects are only updated and that data is not deleted.
You can use multi-path updates.
var userRef = ref.child(hashedEmail);
var updateObject = {
name: 'Rohan Dalvi',
"externalLinks/website": 'mywebsite'
};
userRef.update(updateObject);
By using the "externalLinks/website" syntax in the object literal it will treat the nested path as an update and not a set for the nested object. This keeps nested data from being deleted.
This question provides a more recent solution that works with cloud firestore.
Rather than using "/", one may use "." instead:
var userRef = ref.child(hashedEmail);
var updateObject = {
name: 'Rohan Dalvi',
"externalLinks.website": 'mywebsite'
};
userRef.update(updateObject);
To update nested object/map/dictionary in firebase database, you can use Firestore.Encoder to class/struct that is Codable.
Here is a Swift code example:
Models:
import FirebaseFirestore
import FirebaseFirestoreSwift
// UserDetails Model
class UserDetailsModel: Codable {
let name: String,
externalLinks: ExternalLinkModel
}
// UserDetails Model
class ExternalLinkModel: Codable {
let website: String
}
Calling Firebase:
import FirebaseFirestore
import FirebaseFirestoreSwift
let firestoreEncoder = Firestore.Encoder()
let fields: [String: Any] = [
// using firestore encoder to convert object to firebase map
"externalLinks": try! firestoreEncoder.encode(externalLinkModel)
]
db.collection(path)
.document(userId)
.updateData(fields, completion: { error in
...
})

How to find a record both by id and query parameters in Ember

I'm trying to use ember-data to send a request via id and query parameters to an endpoint. The end output of the ajax call would be http://api.example.com/invoices/1?key=value. As far as I know, ember-data's store doesn't have a native way to find by both id and query parameters (neither of the following worked):
// outputs http://api.example/com/invoices/1
this.store.find('invoice', 1);
// outputs http://api.example.com/invoices?id=1&key=value
this.store.find('invoice, {id: 1, key: value});
Instead, I've been attempting to modify the invoice adapter. Our backend is Django, so we're using the ActiveModelAdapter. I want to override the method that builds the url so that if id is present in the query object, it will automatically remove it and append it to the url instead before turning the rest of the query object into url parameters.
The only problem is that I can't figure out which method to override. I've looked at the docs for ActiveModelAdapter here, and I've tried overriding the findRecord, buildUrl, urlForFind, and urlForQuery methods, but none of them are getting called for some reason (I've tried logging via console.log and Ember.debug). I know the adapter is working correctly because the namespace is working.
Here's my adapter file:
import DS from 'ember-data';
import config from '../config/environment';
export default DS.ActiveModelAdapter.extend({
namespace: 'v1',
host: config.apiUrl,
// taken straight from the build-url-mixin and modified
// very slightly to test for logging
urlForFindRecord: function(id, modelName, snapshot) {
Ember.debug('urlForFindRecord is being called');
if (this.urlForFind !== urlForFind) {
Ember.deprecate('BuildURLMixin#urlForFind has been deprecated and renamed to `urlForFindRecord`.');
return this.urlForFind(id, modelName, snapshot);
}
return this._buildURL(modelName, id);
},
// taken straight from the build-url-mixin and modified
// very slightly to test for logging
findRecord: function(store, type, id, snapshot) {
Ember.debug('findRecord is being called');
var find = RestAdapter.prototype.find;
if (find !== this.find) {
Ember.deprecate('RestAdapter#find has been deprecated and renamed to `findRecord`.');
return this.find(store, type, id, snapshot);
}
return this.ajax(this.buildURL(type.modelName, id, snapshot, 'findRecord'), 'GET');
},
// taken straight from the build-url-mixin and modified
// very slightly to test for logging
urlForQuery: function(query, modelName) {
Ember.debug('urlForQuery is being called');
if (this.urlForFindQuery !== urlForFindQuery) {
Ember.deprecate('BuildURLMixin#urlForFindQuery has been deprecated and renamed to `urlForQuery`.');
return this.urlForFindQuery(query, modelName);
}
return this._buildURL(modelName);
},
// taken straight from the build-url-mixin and modified
// very slightly to test for logging
_buildURL: function(modelName, id) {
Ember.debug('_buildURL is being called');
var url = [];
var host = get(this, 'host');
var prefix = this.urlPrefix();
var path;
if (modelName) {
path = this.pathForType(modelName);
if (path) { url.push(path); }
}
if (id) { url.push(encodeURIComponent(id)); }
if (prefix) { url.unshift(prefix); }
url = url.join('/');
if (!host && url && url.charAt(0) !== '/') {
url = '/' + url;
}
return url;
},
});
Is there an easier way to accomplish what I'm trying to do without overriding adapter methods? And if not, what method(s) do I need to override?
Thanks in advance for your help!
You can use this.store.findQueryOne('invoice', 1, { key: value });
https://github.com/emberjs/data/pull/2584

Categories

Resources