| name | b24jssdk-frame-ui |
| description | Use B24Frame UI managers (slider, dialog, parent, placement, options, auth) from a Bitrix24 placement iframe app. Covers opening sliders with mobile fallback, picking users and CRM entities, resizing the parent window, placement setValue, persisting app/user options. Load when generating in-frame UI code. |
b24jssdk frame UI
These managers exist only on B24Frame. None of them work for B24Hook or B24OAuth. Always init via:
import { initializeB24Frame } from '@bitrix24/b24jssdk'
const $b24 = await initializeB24Frame()
…and call $b24.destroy() when the page/component unmounts.
Slider — open paths and app pages
const url = $b24.slider.getUrl('/crm/deal/details/1')
const status = await $b24.slider.openPath(url, 1640)
if (status.isOpenAtNewWindow) {
}
await $b24.slider.openSliderAppPage({ some: 'param' })
await $b24.slider.closeSliderAppPage()
openPath returns when the slider closes (or the popup is closed on mobile). Always check isOpenAtNewWindow if you depend on close-detection.
Dialog — pick users
const single = await $b24.dialog.selectUser()
const many = await $b24.dialog.selectUsers()
Dialog — pick CRM entities (selectCRM)
Active method (re-implemented in packages/jssdk/src/frame/dialog.ts:175-235). Returns an object with per-entity-type buckets, each a real Array so you can use .length/.map()/for..of. Buckets for entity types you did not request are undefined.
import type { SelectCRMParams, SelectedCRM } from '@bitrix24/b24jssdk'
const single = await $b24.dialog.selectCRM({
entityType: ['contact'],
multiple: false
})
const contact = single.contact?.[0]
const picked: SelectedCRM = await $b24.dialog.selectCRM({
entityType: ['deal', 'company'],
multiple: true,
value: { deal: ['D_42'], company: ['CO_7'] }
})
for (const deal of picked.deal ?? []) {
console.log(deal.id, deal.title)
}
The id format is per entity:
- lead →
L_<n>
- contact →
C_<n>
- company →
CO_<n>
- deal →
D_<n>
- quote →
Q_<n>
Dialog — pick access targets (selectAccess)
const access = await $b24.dialog.selectAccess({ })
Less commonly used. Returns the parent window's raw access-selection payload — refer to Bitrix24's selectAccess docs for the shape.
Parent — control the iframe in the portal layout
await $b24.parent.fitWindow()
await $b24.parent.resizeWindow(800, 600)
await $b24.parent.resizeWindowAuto(rootEl, 400, 300)
await $b24.parent.setTitle('My App')
await $b24.parent.scrollParentWindow(0)
await $b24.parent.reloadWindow()
await $b24.parent.closeApplication()
setTitle changes the in-page #pagetitle, not the browser tab — to set the browser tab title, open a slider via slider.openSliderAppPage({ bx24_title: '…' }).
For IM:
await $b24.parent.imCallTo( 5, true)
await $b24.parent.imOpenMessenger('chat12')
Placement — context the user opened your app from
$b24.placement.title
$b24.placement.options
$b24.placement.isSliderMode
const iface = await $b24.placement.getInterface()
await $b24.placement.bindEvent('onCrmEntityUpdate', (...args) => {
console.log('host event:', args)
})
await $b24.placement.call('someCommand', { foo: 'bar' })
await $b24.placement.callCustomBind('someCommand', { opt: 1 }, (...args) => {
})
placement.setValue — send a value back to the host placement
Use setValue when your iframe is mounted in a "select-value" placement (e.g. a custom CRM-field selector). The host expects a JSON-serialized string and calls JSON.parse on receipt.
await $b24.placement.setValue('plain string')
await $b24.placement.setValue({ id: 1, title: 'demo' })
await $b24.placement.setValue([1, 2, 3])
Manual form via placement.call('setValue', …) is also supported, but value MUST already be a JSON-serialized string — the SDK throws TypeError otherwise (see packages/jssdk/src/frame/placement.ts:104-113):
await $b24.placement.call('setValue', { value: JSON.stringify({ id: 1 }) })
Options — persist app and per-user settings
await $b24.options.appSet('installComplete', true)
const installed = $b24.options.appGet('installComplete')
await $b24.options.userSet('theme', 'dark')
const theme = $b24.options.userGet('theme')
Values are JSON-serialized server-side. Read returns the parsed value.
For batched/structured options, prefer the helper-level options manager (see b24jssdk-helpers).
Auth — env, refresh, language
const auth = $b24.auth.getAuthData()
if (!auth) {
await $b24.auth.refreshAuth()
}
const lang = $b24.getLang()
const sid = $b24.getAppSid()
The SDK auto-refreshes auth on 401 — manual refreshAuth() is rarely needed.
Lifecycle template (Vue 3)
import { onMounted, onBeforeUnmount, ref } from 'vue'
import { initializeB24Frame, type B24Frame } from '@bitrix24/b24jssdk'
const $b24 = ref<B24Frame | null>(null)
onMounted(async () => {
$b24.value = await initializeB24Frame()
await $b24.value.parent.setTitle('My App')
await $b24.value.parent.fitWindow()
})
onBeforeUnmount(() => {
$b24.value?.destroy()
})
Anti-patterns
- ❌ Using
B24Frame outside a Bitrix24 placement — initializeB24Frame() will hang waiting for the parent handshake. Use B24Hook for non-frame contexts.
- ❌ Calling slider / dialog APIs before
await initializeB24Frame() resolves.
- ❌
$b24.placement.call('setValue', { value: { id: 1 } }) — throws because value is not a string. Use $b24.placement.setValue({ id: 1 }) or stringify yourself.
- ❌ Storing secrets in
options.appSet — placement options are visible to everyone with access to the placement.
- ❌ Treating an absent
selectCRM bucket as an empty array — they are undefined. Use picked.deal ?? [].