Comments (2)
Hi @brianchu, this is a problem that arrises from the definition of the grammar for Beagle expressions:
Grammar
Below, "`" is used to group symbols and "/" to represent regular expressions. "|", outside a regular expression, means or.
Expression = @{Operation | Value}
Operation = Name(`Params | )`
Name = /\w[\w\d_]*/
Params = `Param,Params` | Param)
Param = Operation | Value
Value = State | Literal
State = /^(?!(true$|false$|null$|'|\d))[a-z|A-Z|_](\w|(\[\d+\])|(\.\w))*$/
Literal = String | Number | true | false | null
String = /^'([^'\\]|(\\.))*'$/
Number = /^\d+$/
Problem
Any accessed property is identified by State
in the grammar, and just like most programming languages, you can't have symbols like space, plus, minus (hyphen), space, brackets, etc. This is so we don't mix a variable access with some other syntax element.
In truth, considering we don't currently use the minus operator, we could support hyphen on keys without any issue. But, it wouldn't solve the other scenarios and we'd be preventing us from extending the language to include infix operators in the future.
We are currently developing some new server driven libraries to work with SwiftUI and Compose. In these new libraries we'll extend the grammar to include new functionalities, one of them is dynamic state access, which will solve this issue; example: "myState['my-key $*-with-special-characters']". Unfortunately, we can't bring this to Beagle yet, considering it would require a very high amount of work and we have other priorities (like the aforementioned libs).
A solution that can be used now
As you said, one solution is to do a transformation before accessing it. This can be done via a custom operation.
First, you should create a custom operation in the frontend. I'm gonna give you an example on React:
function sanitizeKey(key: string): string {
// replaces both hyphens and spaces with underscores
return key.replace(/[\s\-]/g, '_')
}
function sanitize(data?: any): any {
if (Array.isArray(data)) {
return data.map(sanitize)
}
if (data != null && typeof data == 'object') {
let result: object = {}
Object.keys(data).forEach(key => {
result[sanitizeKey(key)] = sanitize(data[key])
})
return result
}
return data
}
let beagle = createBeagleUIService({
baseUrl: '',
customOperations: {
sanitize,
},
components: {},
})
Then, in the backend, assuming you're setting a Beagle Context from a sendRequest action, you should use the new operation before setting the context (I'll call it result
in the next example):
{
"_beagleAction_": "beagle:sendRequest",
"url": "your_url",
"onSuccess": [{
"_beagleAction_": "beagle:setContext",
"contextId": "result",
"value": "@{sanitize(onSuccess.data)}"
}]
}
Another solution that can be used now
You can also create a custom operation called get
:
function get(data: any, key: string): any {
return (data != null && typeof data == 'object') ? data[key] : null
}
let beagle = createBeagleUIService({
baseUrl: '',
customOperations: {
get,
},
components: {},
})
Then, in the backend, you can access the data with this custom operation (I'll assume your context is called result
):
{
"_beagleComponent_": "beagle:text",
"text": "get(result, 'some-other-key-you-know-can-look-like-this')",
}
The only problem with this approach is that, if your data is deeply nested, you'll have a lot of nested calls to get
.
from beagle.
I'm closing this issue due to inactivity. Please, fell free to reopen this if necessary.
from beagle.
Related Issues (20)
- "PositionType": "Absolute" doesn't work HOT 2
- make beagle:container fit to content width HOT 1
- iOS: How can i convert ServerDrivenComponent to UIView with style
- feat: iOS: make BeagleScreenViewController -> convenience init(_ component: ServerDrivenComponent..) public HOT 8
- Height of a ServerDrivenComponent in Swift(UI) HOT 19
- ListView with section header HOT 4
- Can't access ListView initializer for iOS SDK HOT 2
- How to tell when other component scroll into view? HOT 13
- How to animate Component? HOT 3
- Reusable custom component in JSON level HOT 3
- All Platforms: Modally presented popover server driven components. HOT 4
- Custom component using multiple built-in components doesn't nested HOT 3
- Support for GZIP compression for smaller payload JSON HOT 5
- Testing auto-reply
- Creating listview programmatically will result in crash with "java.lang.IllegalArgumentException: RecyclerView Id can't be -1" HOT 7
- ListView and GridView padding doesn't work in Android platform HOT 1
- Context data not getting passed HOT 3
- BeagleScreenViewController Lifecycle Analytics HOT 4
- Broken link in CONTRIBUTING.md documentation
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from beagle.